#include "burnint.h"
#include "taito_ic.h"
#include "taito.h"

static UINT8 CurrentBank;

// Superman C-Chip
static UINT8 SupermanPort = 0;

static const UINT8 superman_code[40] =
{
	0x48, 0xe7, 0x80, 0x80,	            /* MOVEM.L  D0/A0,-(A7)   ( Preserve Regs ) */
	0x20, 0x6d, 0x1c, 0x40,             /* MOVEA.L  ($1C40,A5),A0 ( Load sound pointer in A0 ) */
	0x30, 0x2f, 0x00, 0x0c,             /* MOVE.W   ($0C,A7),D0   ( Fetch sound number ) */
	0x10, 0x80,                         /* MOVE.B   D0,(A0)       ( Store it on sound pointer ) */
	0x52, 0x88,                         /* ADDQ.W   #1,A0         ( Increment sound pointer ) */
	0x20, 0x3c, 0x00, 0xf0, 0x1c, 0x40, /* MOVE.L   #$F01C40,D0   ( Load top of buffer in D0 ) */
	0xb1, 0xc0,                         /* CMPA.L   D0,A0         ( Are we there yet? ) */
	0x66, 0x04,                         /* BNE.S    *+$6          ( No, we arent, skip next line ) */
	0x41, 0xed, 0x1c, 0x20,             /* LEA      ($1C20,A5),A0 ( Point to the start of the buffer ) */
	0x2b, 0x48, 0x1c, 0x40,	            /* MOVE.L   A0,($1C40,A5) ( Store new sound pointer ) */
	0x4c, 0xdf, 0x01, 0x01,	            /* MOVEM.L  (A7)+, D0/A0  ( Restore Regs ) */
	0x4e, 0x75                          /* RTS                    ( Return ) */
};

UINT16 SupermanCChipCtrlRead()
{
	return 0x01;
}

UINT16 SupermanCChipRamRead(UINT32 Offset, UINT8 Input1, UINT8 Input2, UINT8 Input3)
{
	if (CurrentBank == 0) {
		switch (Offset) {
			case 0x00: return Input1;
			case 0x01: return Input2;
			case 0x02: return Input3;
			case 0x03: return SupermanPort;
		}
	}
	
	if (CurrentBank == 1 && Offset <= 0xff)	{
		if (Offset < 40) {
			return superman_code[Offset];
		} else {
			return 0;
		}
	}

	if (CurrentBank == 2) {
		switch (Offset) {
			case 0x000: return 0x47;
			case 0x001: return 0x57;
			case 0x002: return 0x4b;
		}
	}
	
	return 0;
}

void SupermanCChipCtrlWrite()
{

}

void SupermanCChipBankWrite(UINT16 Data)
{
	CurrentBank = Data & 7;
}

void SupermanCChipRamWrite(UINT32 Offset, UINT16 Data)
{
	if (CurrentBank == 0 && Offset == 0x03)	{
		SupermanPort = Data;
	}
}

void SupermanCChipReset()
{
	CurrentBank = 0;
	SupermanPort = 0;
}

void SupermanCChipInit()
{
	CurrentBank = 0;
	SupermanPort = 0;
	
	TaitoIC_SupermanCChipInUse = 1;
}

void SupermanCChipExit()
{
	CurrentBank = 0;
	SupermanPort = 0;
}

void SupermanCChipScan(INT32 nAction)
{
	if (nAction & ACB_DRIVER_DATA) {
		SCAN_VAR(CurrentBank);
		SCAN_VAR(SupermanPort);
	}
}

// Mega Blast

static UINT8 *MegabCChipRam;

UINT16 MegabCChipRead(UINT32 Offset)
{
	if (Offset == 0x401) {
		return 0x01;
	}

	return MegabCChipRam[Offset];
}

void MegabCChipWrite(UINT32 Offset, UINT16 Data)
{
	MegabCChipRam[Offset] = Data;
}

void MegabCChipReset()
{
	memset(MegabCChipRam, 0, 0x800);	
}

void MegabCChipInit()
{
	MegabCChipRam = (UINT8*)BurnMalloc(0x800);
	memset(MegabCChipRam, 0, 0x800);
	
	TaitoIC_MegabCChipInUse = 1;
}

void MegabCChipExit()
{
	BurnFree(MegabCChipRam);
}

void MegabCChipScan(INT32 nAction)
{
	struct BurnArea ba;
	
	if (nAction & ACB_MEMORY_RAM) {
		memset(&ba, 0, sizeof(ba));
		ba.Data	  = MegabCChipRam;
		ba.nLen	  = 0x800;
		ba.szName = "CChip Ram";
		BurnAcb(&ba);
	}
}

// Rainbow Islands C-Chip

static UINT8 *CRAM[8];
static INT32 ExtraVersion;

struct CBANK
{
	const UINT8* data;
	size_t size;
};

static const UINT8 CROM_BANK1[] =
{
    0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x0A, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x0A, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x0A, 0x0B, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x09, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x05, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x05, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
	0x04, 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06,
	0x08, 0x08, 0x0A, 0x0C, 0x0C, 0x0E, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18,
	0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30,
	0x32, 0x58, 0x5A, 0x5C, 0x5E, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C,
	0x6E, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E, 0x7E, 0x7E, 0x80,
	0x82, 0x86, 0x86, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A
};

static const UINT8 CROM_BANK2[] =
{
	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
	0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
	0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43,
	0x44, 0x45, 0x46, 0x47, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
	0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x10, 0x10, 0x12, 0x12,
	0x14, 0x14, 0x16, 0x20, 0x22, 0x16, 0x20, 0x22, 0x16, 0x16, 0x20, 0x20,
	0x22, 0x22
};

static const UINT8 CROM_BANK4_WORLD0[] =
{
	0x28, 0x00, 0x2C, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00,
	0x40, 0x00, 0x44, 0x00, 0x48, 0x00, 0x54, 0x00, 0x58, 0x00, 0x5C, 0x00,
	0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x74, 0x00, 0x78, 0x00, 0x7C, 0x00,
	0x80, 0x00, 0x84, 0x00, 0x32, 0x00, 0x34, 0x00, 0x56, 0x00, 0x58, 0x00,
	0x98, 0x00, 0x96, 0x00, 0x7A, 0x00, 0x7C, 0x00, 0x56, 0x00, 0x58, 0x00,
	0x98, 0x00, 0x96, 0x00, 0x12, 0x01, 0x13, 0x01, 0x1C, 0x01, 0x1D, 0x01,
	0x29, 0x01, 0x28, 0x01, 0x26, 0x01, 0x27, 0x01, 0x2A, 0x01, 0x2B, 0x01,
	0xFA, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x01, 0x02, 0x10, 0x00, 0x10,
	0xD6, 0x00, 0xD8, 0x00, 0xD2, 0x00, 0xD4, 0x00, 0xDE, 0x00, 0xE0, 0x00,
	0xDA, 0x00, 0xDC, 0x00, 0xF4, 0x00, 0xF2, 0x00, 0x36, 0x01, 0x37, 0x01,
	0x38, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3A, 0x01, 0x34, 0x01, 0x35, 0x01,
	0xC9, 0x02, 0xC8, 0x02
};

static const UINT8 CROM_BANK4_WORLD1[] =
{
	0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00,
	0x3C, 0x00, 0x42, 0x00, 0x48, 0x00, 0x4C, 0x00, 0x50, 0x00, 0x54, 0x00,
	0x58, 0x00, 0x5A, 0x00, 0x5C, 0x00, 0x60, 0x00, 0x62, 0x00, 0x64, 0x00,
	0xAA, 0x01, 0xAC, 0x01, 0xCE, 0x01, 0xD0, 0x01, 0x6E, 0x02, 0x70, 0x02,
	0x62, 0x01, 0x64, 0x01, 0x86, 0x01, 0x88, 0x01, 0x6A, 0x02, 0x6C, 0x02,
	0x02, 0x02, 0x04, 0x02, 0x06, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0C, 0x02,
	0x82, 0x02, 0x84, 0x02, 0x0E, 0x02, 0x10, 0x02, 0x22, 0x02, 0x24, 0x02,
	0x86, 0x02, 0x88, 0x02, 0x26, 0x02, 0x2E, 0x02, 0x8A, 0x02, 0x8C, 0x02,
	0x28, 0x10, 0x28, 0x10, 0x8E, 0x02, 0x90, 0x02
};

static const UINT8 CROM_BANK4_WORLD2[] =
{
	0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x46, 0x00, 0x4E, 0x00,
	0x52, 0x00, 0x56, 0x00, 0x5A, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x62, 0x00,
	0x66, 0x00, 0x68, 0x00, 0x6A, 0x00, 0x6E, 0x00, 0x76, 0x00, 0x7E, 0x00,
	0x82, 0x00, 0x86, 0x00, 0x8A, 0x00, 0x01, 0x03, 0x03, 0x03, 0x05, 0x03,
	0x07, 0x03, 0x01, 0x03, 0x03, 0x03, 0x05, 0x03, 0x07, 0x03, 0x23, 0x03,
	0x21, 0x03, 0x25, 0x03, 0x27, 0x03, 0x29, 0x03, 0x2B, 0x03, 0x25, 0x03,
	0x27, 0x03, 0x29, 0x03, 0x2B, 0x03, 0x47, 0x03, 0x23, 0x03,	0x61, 0x03,
	0x63, 0x03, 0x61, 0x03, 0x63, 0x03, 0x67, 0x03, 0x65, 0x03, 0x49, 0x03,
	0x49, 0x03, 0x67, 0x03, 0x65, 0x03, 0x69, 0x03, 0x69, 0x03, 0xC9, 0x03,
	0xC7, 0x03, 0x85, 0x03, 0x87, 0x03, 0x89, 0x03, 0x8B, 0x03, 0x85, 0x03,
	0x87, 0x03, 0x89, 0x03, 0x8B, 0x03, 0xC9, 0x03, 0xC7, 0x03, 0xAB, 0x03,
	0xAD, 0x03, 0xAF, 0x03, 0xC1, 0x03, 0xC5, 0x03, 0xC3, 0x03
};

static const UINT8 CROM_BANK4_WORLD3[] =
{
	0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00,
	0x48, 0x00, 0x4A, 0x00, 0x4C, 0x00, 0x50, 0x00, 0x54, 0x00, 0x58, 0x00,
	0x5C, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00, 0x6C, 0x00,
	0x70, 0x00, 0x7A, 0x00, 0x84, 0x00, 0x88, 0x00, 0xA2, 0x00, 0xBC, 0x00,
	0x51, 0x04, 0x53, 0x04, 0x51, 0x04, 0x53, 0x04, 0x51, 0x04, 0x51, 0x04,
	0x55, 0x04, 0x57, 0x04, 0x55, 0x04, 0x57, 0x04, 0x55, 0x04, 0x55, 0x04,
	0x59, 0x04, 0x59, 0x04, 0x59, 0x04, 0x9F, 0x04, 0x5D, 0x04, 0x5B, 0x04,
	0x5D, 0x04, 0x5B, 0x04, 0x95, 0x04, 0x93, 0x04, 0x5F, 0x04, 0x5F, 0x04,
	0x99, 0x04, 0x97, 0x04, 0x75, 0x04, 0x77, 0x04, 0x7F, 0x04, 0x91, 0x04,
	0x9D, 0x04, 0x9B, 0x04, 0xB1, 0x04, 0xB3, 0x04, 0xB5, 0x04, 0xB7, 0x04,
	0xB9, 0x04, 0xB1, 0x04, 0xB3, 0x04, 0xB5, 0x04, 0xB7, 0x04, 0xB9, 0x04,
	0xBD, 0x04, 0xBB, 0x04, 0xD6, 0x04, 0xD7, 0x04, 0xD8, 0x04, 0xD9, 0x04,
	0xDA, 0x04, 0xDB, 0x04, 0xDC, 0x04, 0xDD, 0x04, 0xDE, 0x04, 0xDF, 0x04,
	0xE0, 0x04, 0xE1, 0x04, 0xE2, 0x04, 0xD6, 0x04, 0xD7, 0x04, 0xD8, 0x04,
	0xD9, 0x04, 0xDA, 0x04, 0xDB, 0x04, 0xDC, 0x04, 0xDD, 0x04, 0xDE, 0x04,
	0xDF, 0x04, 0xE0, 0x04, 0xE1, 0x04, 0xE2, 0x04, 0x12, 0x05, 0x11, 0x05
};

static const UINT8 CROM_BANK4_WORLD4[] =
{
	0x24, 0x00, 0x24, 0x00, 0x34, 0x00, 0x38, 0x00, 0x38, 0x00, 0x60, 0x00,
	0x64, 0x00, 0x64, 0x00, 0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x90, 0x00,
	0x94, 0x00, 0x94, 0x00, 0x96, 0x00, 0x9A, 0x00, 0x9A, 0x00, 0xB2, 0x00,
	0x56, 0x05, 0x57, 0x05, 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05,
	0x5C, 0x05, 0x5D, 0x05, 0x87, 0x05, 0x86, 0x05, 0x5E, 0x05, 0x5F, 0x05,
	0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x5E, 0x05, 0x5F, 0x05,
	0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x64, 0x05, 0x65, 0x05,
	0x66, 0x05, 0x67, 0x05, 0x66, 0x05, 0x65, 0x05, 0x64, 0x05, 0x63, 0x05,
	0x85, 0x05, 0x84, 0x05, 0x68, 0x05, 0x69, 0x05, 0x6A, 0x05, 0x6B, 0x05,
	0x6C, 0x05, 0x6D, 0x05, 0x6E, 0x05, 0x6F, 0x05, 0x70, 0x05,	0x71, 0x05,
	0x72, 0x05, 0x6D, 0x05, 0x89, 0x05, 0x88, 0x05, 0x73, 0x05, 0x74, 0x05,
	0x75, 0x05, 0x76, 0x05, 0x77, 0x05, 0x78, 0x05, 0x79, 0x05, 0x7A, 0x05,
	0x8B, 0x05, 0x8A, 0x05, 0x7B, 0x05, 0x8C, 0x05, 0x8C, 0x05, 0x4A, 0x05,
	0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, 0x50, 0x05,
	0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x83, 0x05,
	0x82, 0x05
};

static const UINT8 CROM_BANK4_WORLD5[] =
{
	0x24, 0x00, 0x2C, 0x00, 0x34, 0x00, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00,
	0x4C, 0x00, 0x54, 0x00, 0x5C, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00,
	0x6C, 0x00, 0x78, 0x00, 0x84, 0x00, 0x88, 0x00, 0x8C, 0x00, 0x90, 0x00,
	0x43, 0x06, 0x45, 0x06, 0x47, 0x06, 0x49, 0x06, 0x43, 0x06, 0x45, 0x06,
	0x47, 0x06, 0x49, 0x06, 0x65, 0x06, 0x63, 0x06, 0x6D, 0x06, 0x6F, 0x06,
	0x71, 0x06, 0x83, 0x06, 0x6D, 0x06, 0x6F, 0x06, 0x71, 0x06, 0x83, 0x06,
	0x6F, 0x06, 0x83, 0x06, 0x85, 0x06, 0x87, 0x06, 0x89, 0x06, 0x8B, 0x06,
	0x85, 0x06, 0x87, 0x06, 0x89, 0x06, 0x8B, 0x06, 0x8F, 0x06, 0x8D, 0x06,
	0xAD, 0x06, 0xAF, 0x06, 0xAD, 0x06, 0xAF, 0x06, 0xC3, 0x06, 0xB1, 0x06,
	0xC5, 0x06, 0xC7, 0x06, 0xC9, 0x06, 0xCB, 0x06, 0xCD, 0x06, 0xCF, 0x06,
	0xC5, 0x06, 0xC7, 0x06, 0xC9, 0x06, 0xCB, 0x06, 0xCD, 0x06, 0xCF, 0x06,
	0xCB, 0x06, 0xC5, 0x06, 0xE3, 0x06, 0xD1, 0x06, 0xE3, 0x06, 0xD1, 0x06,
	0xE5, 0x06, 0xE3, 0x06
};

static const UINT8 CROM_BANK4_WORLD6[] =
{
	0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x46, 0x00, 0x4E, 0x00,
	0x52, 0x00, 0x5A, 0x00, 0x62, 0x00, 0x66, 0x00, 0x6A, 0x00, 0x6E, 0x00,
	0x72, 0x00, 0x76, 0x00, 0x7A, 0x00, 0x7E, 0x00, 0x82, 0x00, 0x86, 0x00,
	0x8A, 0x00, 0x8E, 0x00, 0x92, 0x00, 0x5B, 0x08, 0x5D, 0x08, 0x5F, 0x08,
	0x61, 0x08, 0x5B, 0x08, 0x5D, 0x08, 0x5F, 0x08, 0x61, 0x08, 0x65, 0x08,
	0x63, 0x08, 0x67, 0x08, 0x69, 0x08, 0x7B, 0x08, 0x7D, 0x08, 0x67, 0x08,
	0x69, 0x08, 0x7B, 0x08, 0x7D, 0x08, 0x81, 0x08, 0x7F, 0x08, 0x83, 0x08,
	0x85, 0x08, 0x87, 0x08, 0x89, 0x08, 0x83, 0x08, 0x85, 0x08,	0x87, 0x08,
	0x89, 0x08, 0x9D, 0x08, 0x9B, 0x08, 0x9F, 0x08, 0xA1, 0x08, 0x9F, 0x08,
	0xA1, 0x08, 0xA5, 0x08, 0xA3, 0x08, 0xA7, 0x08, 0xA9, 0x08, 0xA7, 0x08,
	0xA9, 0x08, 0xBD, 0x08, 0xBB, 0x08, 0xBF, 0x08, 0xC1, 0x08, 0xBF, 0x08,
	0xC1, 0x08, 0xC5, 0x08, 0xC3, 0x08, 0xDD, 0x08, 0xDF, 0x08, 0xDD, 0x08,
	0xDF, 0x08, 0xE1, 0x08, 0xC7, 0x08, 0xC7, 0x08
};

static const UINT8 CROM_BANK4_WORLD7[] =
{
	0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x42, 0x00, 0x46, 0x00,
	0x4A, 0x00, 0x4E, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5E, 0x00, 0x66, 0x00,
	0x6A, 0x00, 0x6E, 0x00, 0x72, 0x00,	0x76, 0x00, 0x78, 0x00, 0x7A, 0x00,
	0x7E, 0x00, 0x82, 0x00, 0x86, 0x00, 0xA1, 0x05, 0xA3, 0x05, 0xA5, 0x05,
	0xA7, 0x05, 0xA9, 0x05, 0xAB, 0x05, 0xAD, 0x05, 0xAF, 0x05,	0xC1, 0x05,
	0xC3, 0x05,	0xC5, 0x05, 0xC7, 0x05, 0xC5, 0x05, 0xC7, 0x05, 0xE3, 0x05,
	0xE5, 0x05, 0xE7, 0x05, 0xE9, 0x05, 0xED, 0x05, 0xEF, 0x05, 0x03, 0x06,
	0x05, 0x06, 0x58, 0x10, 0x5A, 0x10, 0x5C, 0x10, 0x5E, 0x10, 0x58, 0x10,
	0x5A, 0x10, 0x5C, 0x10, 0x5E, 0x10, 0x62, 0x10, 0x64, 0x10, 0x25, 0x06,
	0x27, 0x06, 0x25, 0x06, 0x27, 0x06, 0x29, 0x06, 0x2B, 0x06, 0x2F, 0x06,
	0x2F, 0x06, 0x2D, 0x06, 0x2F, 0x06, 0x9C, 0x05, 0x9D, 0x05, 0x9C, 0x05,
	0x9D, 0x05, 0x78, 0x10, 0x9D, 0x05
};

static const UINT8 CROM_BANK4_WORLD8[] =
{
	0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x40, 0x00,
	0x42, 0x00, 0x46, 0x00, 0x4A, 0x00, 0x4E, 0x00, 0x5C, 0x00, 0x6A, 0x00,
	0x6E, 0x00, 0x70, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7A, 0x00, 0x7E, 0x00,
	0x82, 0x00, 0x88, 0x00, 0x8E, 0x00, 0x92, 0x00, 0x96, 0x00, 0x9A, 0x00,
	0xB0, 0x09, 0xB2, 0x09, 0xB0, 0x09, 0xB2, 0x09, 0xB4, 0x09, 0xB0, 0x09,
	0xB6, 0x09, 0xB6, 0x09, 0xB6, 0x09, 0xB8, 0x09, 0xBA, 0x09, 0xB8, 0x09,
	0xBA, 0x09, 0xBC, 0x09, 0xB8, 0x09, 0xBE, 0x09, 0xD0, 0x09, 0xD2, 0x09,
	0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xBE, 0x09, 0xD0, 0x09,
	0xD2, 0x09, 0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xDC, 0x09,
	0xD4, 0x09, 0xDE, 0x09, 0xDE, 0x09, 0xF4, 0x09, 0xDE, 0x09, 0xF6, 0x09,
	0xF8, 0x09, 0xF6, 0x09, 0xF8, 0x09, 0x1A, 0x0A, 0xF6, 0x09, 0x1C, 0x0A,
	0x1E, 0x0A, 0x30, 0x0A, 0x1C, 0x0A, 0x1E, 0x0A, 0x30, 0x0A, 0x32, 0x0A,
	0x1C, 0x0A, 0x34, 0x0A, 0x36, 0x0A, 0x34, 0x0A, 0x36, 0x0A, 0x38, 0x0A,
	0x36, 0x0A
};

static const UINT8 CROM_BANK4_WORLD9[] =
{
	0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x50, 0x00,
	0x58, 0x00, 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x78, 0x00, 0x80, 0x00,
	0x88, 0x00, 0x90, 0x00, 0x98, 0x00, 0xA0, 0x00, 0xA6, 0x00, 0xAC, 0x00,
	0xB4, 0x00, 0xBC, 0x00, 0xC4, 0x00, 0xCC, 0x00, 0xD0, 0x00, 0xD4, 0x00,
	0xAF, 0x0B, 0xB1, 0x0B, 0xAF, 0x0B, 0xB1, 0x0B, 0xB3, 0x0B, 0xB5, 0x0B,
	0xEF, 0x0F, 0xF0, 0x0F, 0xB7, 0x0B, 0xB9, 0x0B, 0xBB, 0x0B, 0xBD, 0x0B,
	0xB7, 0x0B, 0xB9, 0x0B, 0xBB, 0x0B, 0xBD, 0x0B, 0xCF, 0x0B, 0xD1, 0x0B,
	0xF1, 0x0F, 0xF2, 0x0F, 0x47, 0x11, 0x49, 0x11, 0x4B, 0x11, 0x4D, 0x11,
	0x47, 0x11, 0x49, 0x11, 0x4B, 0x11, 0x4D, 0x11, 0x4F, 0x11, 0x51, 0x11,
	0xFD, 0x0F, 0xFE, 0x0F, 0xEF, 0x0B, 0xF1, 0x0B, 0xF3, 0x0B, 0xF5, 0x0B,
	0xEF, 0x0B, 0xF1, 0x0B, 0xF3, 0x0B, 0xF5, 0x0B, 0xF7, 0x0B, 0xF9, 0x0B,
	0xF3, 0x0F, 0xF4, 0x0F, 0xFB, 0x0B, 0xFD, 0x0B, 0x0F, 0x0C, 0x11, 0x0C,
	0xFB, 0x0B, 0xFD, 0x0B, 0x0F, 0x0C, 0x11, 0x0C, 0x13, 0x0C, 0x15, 0x0C,
	0xF5, 0x0F, 0xF6, 0x0F, 0x6B, 0x11, 0x6D, 0x11, 0x6F, 0x11, 0x6B, 0x11,
	0x6D, 0x11, 0x6F, 0x11, 0x1D, 0x0C, 0x2F, 0x0C, 0xF7, 0x0F, 0xF8, 0x0F,
	0x31, 0x0C, 0x33, 0x0C, 0x35, 0x0C, 0x37, 0x0C, 0x31, 0x0C, 0x33, 0x0C,
	0x35, 0x0C, 0x37, 0x0C, 0x39, 0x0C, 0x3B, 0x0C, 0xF9, 0x0F, 0xFA, 0x0F,
	0x3D, 0x0C, 0x4F, 0x0C, 0x3D, 0x0C, 0x4F, 0x0C, 0x51, 0x0C, 0x53, 0x0C,
	0xFB, 0x0F, 0xFC, 0x0F, 0xDC, 0x02, 0xDD, 0x02
};

static const UINT8 CROM_BANK5_WORLD0[] =
{
	0x1C, 0x00, 0x1C, 0x00, 0x32, 0x00, 0x32, 0x00, 0x48, 0x00, 0x48, 0x00,
	0xB6, 0x00, 0x5E, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x74, 0x00, 0x74, 0x00,
	0x8A, 0x00, 0x8A, 0x00, 0x01, 0x08, 0xC4, 0x19, 0x49, 0x08, 0xC4, 0x19,
	0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01,
	0xFF, 0xFF, 0xC9, 0x08, 0xD3, 0x19, 0x09, 0x09, 0xC4, 0x19, 0x45, 0x09,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF,
	0x80, 0x09, 0xC5, 0x19, 0xC8, 0x09, 0xC3, 0x19, 0x04, 0x0A, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A,
	0xC7, 0x29, 0x89, 0x0A, 0xC7, 0x29, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x0B, 0x45, 0x29,
	0x49, 0x0B, 0x43, 0x29, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x49, 0x0B, 0x47, 0x29, 0x49, 0x0B,
	0x47, 0x29, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02,
	0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x0B, 0xC1, 0x18, 0x08, 0x0C, 0xC1, 0x18,
	0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01,
	0xFF, 0xFF, 0x80, 0x04, 0xC0, 0x39, 0x80, 0x0C, 0xC3, 0x39, 0xC4, 0x0C,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x3C, 0x00, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD1[] =
{
	0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00,
	0x01, 0x08, 0xC4, 0x19, 0x49, 0x08, 0xC4, 0x19, 0x84, 0x08, 0xC7, 0x18,
	0xE6, 0x5A, 0xBF, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x08,
	0xC4, 0x19, 0x09, 0x09, 0xC4, 0x19, 0x44, 0x09, 0xC7, 0x18, 0xEB, 0x5A,
	0xC1, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0x45, 0x1A,
	0x89, 0x0A, 0x43, 0x1A, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x11, 0xC1, 0x29, 0xC9, 0x11,
	0xC1, 0x29, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02,
	0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0xC0, 0x19, 0x49, 0x03, 0xC0, 0x19,
	0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, 0x00, 0x01,
	0xFF, 0xFF, 0xC9, 0x03, 0xC0, 0x39, 0x09, 0x04, 0xC0, 0x39, 0x44, 0x0C,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD2[] =
{
	0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00,
	0x92, 0x00, 0x01, 0x18, 0xC7, 0x39, 0x49, 0x18, 0xC5, 0x39, 0x84, 0x08,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF,
	0xC1, 0x08, 0xC7, 0x39, 0x09, 0x09, 0xC5, 0x39, 0x44, 0x09, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x09,
	0x47, 0x49, 0xC9, 0x09, 0x45, 0x49, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x02, 0xC7, 0x49,
	0x89, 0x02, 0xC5, 0x49, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0x43, 0x29, 0x49, 0x03,
	0x42, 0x29, 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01,
	0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x1B, 0x43, 0x29, 0x09, 0x1C, 0x42, 0x29,
	0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0x81, 0x0C, 0x43, 0x39, 0xC9, 0x0C, 0x41, 0x39, 0x04, 0x0D,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD3[] =
{
	0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00,
	0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0xC1, 0x39, 0x49, 0x08, 0xC1, 0x39,
	0x84, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0xC1, 0x08, 0xC1, 0x39, 0x09, 0x09, 0xC1, 0x39, 0x44, 0x09,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF,
	0x81, 0x01, 0x40, 0x39, 0xC9, 0x01, 0x40, 0x39, 0x04, 0x0A, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A,
	0xC3, 0x39, 0x89, 0x0A, 0xC3, 0x39, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0x40, 0x19,
	0x49, 0x03, 0x40, 0x19, 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xD3, 0x49, 0x09, 0x0C,
	0xC9, 0x49, 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x78, 0x00,
	0x00, 0x01, 0xFF, 0xFF, 0x81, 0x24, 0xC7, 0x1B, 0xC9, 0x24, 0xC7, 0x1B,
	0x04, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0x40, 0x65, 0x41, 0x29, 0x88, 0x65, 0x40, 0x29, 0xC4, 0x0D,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD4[] =
{
	0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00,
	0x00, 0x38, 0xC6, 0x18, 0x48, 0x38, 0xC6, 0x18, 0x84, 0x08, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x98,
	0xC9, 0x18, 0x08, 0x99, 0xC9, 0x18, 0x44, 0x09, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x59, 0xC9, 0x18,
	0xC8, 0x59, 0xC9, 0x18, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x40, 0x3A, 0xC4, 0x18, 0x88, 0x3A,
	0xC4, 0x18, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
	0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0x80, 0x18, 0x48, 0x03, 0x80, 0x18,
	0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0xC0, 0x5B, 0x85, 0x31, 0x08, 0x5C, 0x85, 0x31, 0x44, 0x0C,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD5[] =
{
	0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00,
	0x01, 0x18, 0x43, 0x39, 0x49, 0x18, 0x43, 0x39, 0x85, 0x08, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x18,
	0xC3, 0x39, 0x09, 0x19, 0xC3, 0x39, 0x45, 0x09, 0xC3, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x19, 0x43, 0x39,
	0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0x43, 0x19, 0x89, 0x0A,
	0x43, 0x19, 0xC5, 0x0A, 0x47, 0x19, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
	0x00, 0x00, 0xFF, 0xFF, 0x01, 0x2B, 0xC3, 0x19, 0x49, 0x2B, 0xC2, 0x19,
	0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0xC1, 0x0B, 0xC3, 0x18, 0x09, 0x0C, 0xC3, 0x18, 0x45, 0x0C,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD6[] =
{
	0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00,
	0x92, 0x00, 0x01, 0x18, 0x45, 0x39, 0x49, 0x18, 0x43, 0x39, 0x85, 0x08,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF,
	0xC1, 0x18, 0x45, 0x39, 0x09, 0x19, 0x43, 0x39, 0x45, 0x09, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x19,
	0x45, 0x39, 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0xC7, 0x39,
	0x89, 0x0A, 0xC5, 0x39, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x68, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x0B, 0x05, 0x42, 0x49, 0x0B,
	0x03, 0x42, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
	0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xC5, 0x39, 0x09, 0x0C, 0xC3, 0x39,
	0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0x81, 0x0C, 0x4D, 0x0A, 0xC9, 0x0C, 0x4B, 0x0A, 0x05, 0x0D,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD7[] =
{
	0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00,	0x7C, 0x00,
	0x92, 0x00, 0x01, 0x18, 0xC5, 0x41, 0x49, 0x18, 0xC3, 0x41, 0x85, 0x08,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF,
	0xC1, 0x08, 0xC5, 0x41, 0x09, 0x09, 0xC3, 0x41, 0x45, 0x09, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x09,
	0x45, 0x4A, 0xC9, 0x09, 0x43, 0x4A, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x1A, 0xC5, 0x39,
	0x81, 0x1A, 0xC3, 0x39, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0xE0, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x0B, 0x45, 0x5A, 0x49, 0x0B,
	0x43, 0x5A, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01,
	0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x03, 0xC5, 0x59, 0x09, 0x04, 0xC3, 0x59,
	0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0x80, 0x0C, 0x45, 0x29, 0xC8, 0x0C, 0x43, 0x29, 0x04, 0x0D,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD8[] =
{
	0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00,
	0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0x43, 0x49, 0x49, 0x08, 0x43, 0x49,
	0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0xC1, 0x00, 0x43, 0x39, 0x09, 0x01, 0x43, 0x49, 0x45, 0x01,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,	0xFF, 0xFF,
	0x81, 0x09, 0xC3, 0x59, 0xC9, 0x09, 0xC3, 0x59, 0x05, 0x0A, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x32,
	0xC3, 0x5B, 0x89, 0x32, 0xC3, 0x5B, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0x68, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x03, 0xC3, 0x49,
	0x49, 0x03, 0xC3, 0x49, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xC3, 0x19, 0x09, 0x0C,
	0xC3, 0x19, 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
	0x00, 0x01, 0xFF, 0xFF, 0x81, 0x14, 0xC5, 0x39, 0xC9, 0x14, 0xC3, 0x39,
	0x05, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
	0xFF, 0xFF, 0x41, 0x0D, 0xC7, 0x39, 0x89, 0x0D, 0xC5, 0x39, 0xC5, 0x0D,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK5_WORLD9[] =
{
	0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00,
	0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0x03, 0x1A, 0x49, 0x08, 0x03, 0x1A,
	0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01,
	0xFF, 0xFF, 0xC1, 0x18, 0xC3, 0x18, 0x09, 0x19, 0x03, 0x1A, 0x45, 0x09,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF,
	0x81, 0x19, 0x45, 0x39, 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18,
	0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x1A,
	0x45, 0x18, 0x89, 0x1A, 0x43, 0x18, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
	0xB7, 0x6E, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x1B, 0xC5, 0x18,
	0x49, 0x1B, 0xC3, 0x18, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
	0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x13, 0x47, 0x39, 0x09, 0x14,
	0x45, 0x39, 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05,
	0x00, 0x01, 0xFF, 0xFF, 0x81, 0x1C, 0x45, 0x19, 0xC9, 0x1C, 0x43, 0x19,
	0x05, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01,
	0xFF, 0xFF, 0x41, 0x0D, 0xC5, 0x18, 0x89, 0x0D, 0xC3, 0x18, 0xC5, 0x0D,
	0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF
};

static const UINT8 CROM_BANK6[] =
{
	0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x04,
	0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x30, 0x05, 0x00, 0x00,
	0x00, 0x00, 0x42, 0x00, 0x00, 0x33, 0x04, 0x00, 0x54, 0x40, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x50, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x03, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x33, 0x20, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x33, 0x01,
	0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x34, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x23, 0x02, 0x03, 0x40,
	0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00,
	0x02, 0x22, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x30, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x30, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x32, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x22, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x30, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x22, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x02, 0x02,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
	0x12, 0x12, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x21, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x00, 0x12, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x20, 0x01, 0x22, 0x03, 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x22, 0x03,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x10, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x31,
	0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00,
	0x20, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x33, 0x20, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x30, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00
};

static const UINT8 CROM_BANK6_EXTRA[] =
{
	0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x30,
	0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x04, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x12, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x22, 0x21, 0x02, 0x03,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x33, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x34, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00,
	0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x05, 0x03, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01,
	0x50, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x01, 0x50, 0x00, 0x04, 0x00,
	0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x21,
	0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00,
	0x22, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03,
	0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00,
	0x22, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x44, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x11, 0x12, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x20, 0x32, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x31, 0x12, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x31, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x20, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x33, 0x20, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x30, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00
};

static const UINT8 CROM_BANK7_WORLD0[] = { 0x03, 0x03, 0x03, 0x03, 0x0C, 0x0C, 0x0A, 0x07, 0x0A, 0x0A, 0x08, 0x08, 0x08, 0x08 };
static const UINT8 CROM_BANK7_WORLD1[] = { 0x03, 0x05, 0x01, 0x02, 0x04, 0x04 };
static const UINT8 CROM_BANK7_WORLD2[] = { 0x03, 0x05, 0x07, 0x07, 0x08, 0x08, 0x01 };
static const UINT8 CROM_BANK7_WORLD3[] = { 0x07, 0x07, 0x07, 0x08, 0x05, 0x08, 0x07, 0x0B };
static const UINT8 CROM_BANK7_WORLD4[] = { 0x0A, 0x0B, 0x0A, 0x0A, 0x10, 0x10 };
static const UINT8 CROM_BANK7_WORLD5[] = { 0x05, 0x08, 0x04, 0x08, 0x08, 0x07 };
static const UINT8 CROM_BANK7_WORLD6[] = { 0x04, 0x07, 0x05, 0x08, 0x06, 0x08, 0x03 };
static const UINT8 CROM_BANK7_WORLD7[] = { 0x07, 0x06, 0x06, 0x05, 0x08, 0x07, 0x0A };
static const UINT8 CROM_BANK7_WORLD8[] = { 0x06, 0x05, 0x01, 0x08, 0x05, 0x05, 0x06, 0x08 };
static const UINT8 CROM_BANK7_WORLD9[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };

static const struct CBANK CROM_BANK4[] =
{
	{ CROM_BANK4_WORLD0, sizeof CROM_BANK4_WORLD0 },
	{ CROM_BANK4_WORLD1, sizeof CROM_BANK4_WORLD1 },
	{ CROM_BANK4_WORLD2, sizeof CROM_BANK4_WORLD2 },
	{ CROM_BANK4_WORLD3, sizeof CROM_BANK4_WORLD3 },
	{ CROM_BANK4_WORLD4, sizeof CROM_BANK4_WORLD4 },
	{ CROM_BANK4_WORLD5, sizeof CROM_BANK4_WORLD5 },
	{ CROM_BANK4_WORLD6, sizeof CROM_BANK4_WORLD6 },
	{ CROM_BANK4_WORLD7, sizeof CROM_BANK4_WORLD7 },
	{ CROM_BANK4_WORLD8, sizeof CROM_BANK4_WORLD8 },
	{ CROM_BANK4_WORLD9, sizeof CROM_BANK4_WORLD9 },
};

static const struct CBANK CROM_BANK5[] =
{
	{ CROM_BANK5_WORLD0, sizeof CROM_BANK5_WORLD0 },
	{ CROM_BANK5_WORLD1, sizeof CROM_BANK5_WORLD1 },
	{ CROM_BANK5_WORLD2, sizeof CROM_BANK5_WORLD2 },
	{ CROM_BANK5_WORLD3, sizeof CROM_BANK5_WORLD3 },
	{ CROM_BANK5_WORLD4, sizeof CROM_BANK5_WORLD4 },
	{ CROM_BANK5_WORLD5, sizeof CROM_BANK5_WORLD5 },
	{ CROM_BANK5_WORLD6, sizeof CROM_BANK5_WORLD6 },
	{ CROM_BANK5_WORLD7, sizeof CROM_BANK5_WORLD7 },
	{ CROM_BANK5_WORLD8, sizeof CROM_BANK5_WORLD8 },
	{ CROM_BANK5_WORLD9, sizeof CROM_BANK5_WORLD9 },
};

static const struct CBANK CROM_BANK7[] =
{
	{ CROM_BANK7_WORLD0, sizeof CROM_BANK7_WORLD0 },
	{ CROM_BANK7_WORLD1, sizeof CROM_BANK7_WORLD1 },
	{ CROM_BANK7_WORLD2, sizeof CROM_BANK7_WORLD2 },
	{ CROM_BANK7_WORLD3, sizeof CROM_BANK7_WORLD3 },
	{ CROM_BANK7_WORLD4, sizeof CROM_BANK7_WORLD4 },
	{ CROM_BANK7_WORLD5, sizeof CROM_BANK7_WORLD5 },
	{ CROM_BANK7_WORLD6, sizeof CROM_BANK7_WORLD6 },
	{ CROM_BANK7_WORLD7, sizeof CROM_BANK7_WORLD7 },
	{ CROM_BANK7_WORLD8, sizeof CROM_BANK7_WORLD8 },
	{ CROM_BANK7_WORLD9, sizeof CROM_BANK7_WORLD9 },
};

static const UINT16 cchip_extra_patch[][8] =
{
	{ 0x0168, 0x0078, 0x0168, 0x0168, 0x0168, 0x02D0, 0x0168, 0x003C },
	{ 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x0000, 0x0000 },
	{ 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x0000 },
	{ 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x001E, 0x0168, 0x0168 },
	{ 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000, 0x0000 },
	{ 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000, 0x0000 },
	{ 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000 },
	{ 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x0000 },
	{ 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4 },
	{ 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500 }
};

static const UINT8 cchip_goalin[15][6] =
{
	{ 0x00, 0x00, 0x28, 0x28, 0x50, 0x50 },
	{ 0x00, 0x00, 0x00, 0x00, 0x50, 0x50 },
	{ 0x00, 0x10, 0x20, 0x30, 0x00, 0x10 },
	{ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50 },
	{ 0x00, 0x18, 0x30, 0x00, 0x18, 0x30 },
	{ 0x00, 0x18, 0x30, 0x30, 0x18, 0x00 },
	{ 0x00, 0x28, 0x50, 0x00, 0x28, 0x50 },
	{ 0x00, 0x30, 0x20, 0x50, 0x10, 0x20 },
	{ 0x00, 0x50, 0x00, 0x50, 0x00, 0x50 },
	{ 0x30, 0x18, 0x00, 0x30, 0x18, 0x00 },
	{ 0x30, 0x18, 0x00, 0x00, 0x18, 0x30 },
	{ 0x30, 0x00, 0x10, 0x40, 0x50, 0x20 },
	{ 0x30, 0x20, 0x10, 0x00, 0x10, 0x00 },
	{ 0x50, 0x40, 0x30, 0x20, 0x10, 0x00 },
	{ 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 }
};

static const UINT16 cchip_round_height[] =
{
	0x02DC, 0x03B4, 0x0444, 0x04BC, 0x03B4, 0x0444, 0x05DC, 0x050C,
	0x0594, 0x06B4, 0x06B4, 0x0894, 0x065C, 0x06CC, 0x07BC, 0x08BC,
	0x0704, 0x059C, 0x030C, 0x0504, 0x0504, 0x0564, 0x05CC, 0x0644,
	0x080C, 0x086C, 0x08E4, 0x0954, 0x065C, 0x06D4, 0x0754, 0x07C4,
	0x06D4, 0x0754, 0x0824, 0x0884, 0x080C, 0x086C, 0x08E4, 0x096C,
	0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999,
	0x0999, 0x0999
};

static const UINT32 cchip_round_address[] =
{
	0x030000, 0x030360, 0x030798, 0x030CA8, 0x0311B8, 0x0315F0, 0x031B00, 0x0321C0,
	0x032880, 0x032E68, 0x033600, 0x033D98, 0x0347B8, 0x034E78, 0x035610, 0x035E80,
	0x0368A0, 0x037038, 0x037620, 0x037A58, 0x038118, 0x038700, 0x038CE8, 0x0393A8,
	0x039A68, 0x03A2D8, 0x03AC20, 0x03B568, 0x03BF88, 0x03C648, 0x03CDE0, 0x03D650,
	0x03DEC0, 0x03E658, 0x03EEC8, 0x03F738, 0x040080, 0x0408F0, 0x041238, 0x041B80,
	0x0425A0, 0x042678, 0x042750, 0x042828, 0x042900, 0x0429D8, 0x042AB0, 0x042B88,
	0x042C60, 0x042D38
};

static void RequestRoundData(void)
{
	INT32 round = CRAM[1][0x141]; /* 0...49 */

	memcpy(CRAM[1], CROM_BANK1, sizeof CROM_BANK1);
	memcpy(CRAM[2], CROM_BANK2, sizeof CROM_BANK2);

	CRAM[1][1] = cchip_round_height[round] >> 0;
	CRAM[1][2] = cchip_round_height[round] >> 8;

	CRAM[1][0x142] = cchip_round_address[round] >> 24;
	CRAM[1][0x143] = cchip_round_address[round] >> 16;
	CRAM[1][0x144] = cchip_round_address[round] >> 8;
	CRAM[1][0x145] = cchip_round_address[round] >> 0;

	/* set the secret room or boss flag */

	CRAM[1][0x148] = (round >= 40 || round % 4 == 3);
}

static void RequestWorldData(void)
{
	INT32 world = CRAM[0][0x00D] / 4; /* 0...9 */

	/* the extra version has the world data swapped around */

	if (ExtraVersion)
	{
		static const UINT8 world_swap[] =
		{
			8, 7, 6, 4, 0, 2, 3, 5, 1, 9
		};

		world = world_swap[world];
	}

	/* first two bytes in each bank are left unchanged  */

	memcpy(CRAM[4] + 2, CROM_BANK4[world].data, CROM_BANK4[world].size);
	memcpy(CRAM[5] + 2, CROM_BANK5[world].data, CROM_BANK5[world].size);
	memcpy(CRAM[7] + 2, CROM_BANK7[world].data, CROM_BANK7[world].size);

	/* banks 5 and 6 are different in the extra version */

	if (ExtraVersion)
	{
		INT32 i;

		for (i = 0; i < 8; i++)
		{
			UINT16 patch = cchip_extra_patch[world][i];

			if (patch != 0)
			{
				CRAM[5][CRAM[5][2] + 22 * i + 18] = patch >> 0;
				CRAM[5][CRAM[5][2] + 22 * i + 19] = patch >> 8;
			}
		}

		memcpy(CRAM[6] + 2, CROM_BANK6_EXTRA, sizeof CROM_BANK6_EXTRA);
	}
	else
	{
		memcpy(CRAM[6] + 2, CROM_BANK6, sizeof CROM_BANK6);
	}
}

static void RequestGoalinData(void)
{
	INT32 n = rand() % 15;

	CRAM[1][0x14B] = 0x00; /* x coordinates */
	CRAM[1][0x14D] = 0x10;
	CRAM[1][0x14F] = 0x20;
	CRAM[1][0x151] = 0x38;
	CRAM[1][0x153] = 0x50;
	CRAM[1][0x155] = 0x60;

	CRAM[1][0x14A] = cchip_goalin[n][0]; /* y coordinates */
	CRAM[1][0x14C] = cchip_goalin[n][1];
	CRAM[1][0x14E] = cchip_goalin[n][2];
	CRAM[1][0x150] = cchip_goalin[n][3];
	CRAM[1][0x152] = cchip_goalin[n][4];
	CRAM[1][0x154] = cchip_goalin[n][5];
}

void RainbowCChipUpdate(UINT8 Input1, UINT8 Input2, UINT8 Input3, UINT8 Input4)
{
	if (CRAM[1][0x100] == 1) {
		RequestRoundData();

		CRAM[1][0x100] = 0xFF;
	}

	if (CRAM[5][0x000] == 1) {
		RequestWorldData();

		CRAM[5][0x000] = 0xFF;
	}

	if (CRAM[1][0x149] == 1) {
		RequestGoalinData();

		CRAM[1][0x149] = 0xFF;
	}

	CRAM[0][3] = Input1;
	CRAM[0][4] = Input2;
	CRAM[0][5] = Input3;
	CRAM[0][6] = Input4;
}

UINT16 RainbowCChipCtrlRead()
{
	return 0x01;
}

UINT16 RainbowCChipRamRead(UINT32 Offset)
{
	return CRAM[CurrentBank][Offset];
}

void RainbowCChipCtrlWrite(UINT16)
{

}

void RainbowCChipBankWrite(UINT16 Data)
{
	CurrentBank = Data & 7;
}

void RainbowCChipRamWrite(UINT32 Offset, UINT16 Data)
{
	CRAM[CurrentBank][Offset] = Data;
}

void RainbowCChipReset()
{
	for (INT32 i = 0; i < 8; i++) {
		memset(CRAM[i], 0, 0x400);
	}
	
	ExtraVersion = 0;
	CurrentBank = 0;	
}

void RainbowCChipInit(INT32 Version)
{
	ExtraVersion = Version;
	
	for (INT32 i = 0; i < 8; i++) {
		CRAM[i] = (UINT8*)BurnMalloc(0x400);
		memset(CRAM[i], 0, 0x400);
	}
	
	TaitoIC_RainbowCChipInUse = 1;
}

void RainbowCChipExit()
{
	for (INT32 i = 0; i < 8; i++) {
		BurnFree(CRAM[i]);
	}
	
	ExtraVersion = 0;
	CurrentBank = 0;	
}

void RainbowCChipScan(INT32 nAction)
{
	struct BurnArea ba;
	
	if (nAction & ACB_MEMORY_RAM) {
		for (INT32 i = 0; i < 8; i++) {
			memset(&ba, 0, sizeof(ba));
			ba.Data	  = CRAM[i];
			ba.nLen	  = 0x400;
			ba.szName = "CChip Ram";
			BurnAcb(&ba);
		}
	}
	
	if (nAction & ACB_DRIVER_DATA) {
		SCAN_VAR(CurrentBank);
	}
}

/////////////////////////////////////////////////////////////////////////////////////////

// Operation Wolf C-Chip

#define OPWOLF_REGION_JAPAN		1
#define OPWOLF_REGION_US		2
#define OPWOLF_REGION_WORLD		3
#define OPWOLF_REGION_OTHER		4

static INT32 CChipRegion;

static UINT8 CurrentCmd=0;
static UINT8* CChipRam=0;
static UINT8 CChipLast_7a=0;
static UINT8 CChipLast_04=0;
static UINT8 CChipLast_05=0;
static UINT8 CChipCoinsForCredit[2]={1,1};
static UINT8 CChipCreditsForCoin[2]={1,1};
static UINT8 CChipCoins[2]={0,0};
static UINT8 c588=0, c589=0, c58a=0;

static const UINT16 level_data_00[0xcc] =
{
	0x0480,0x1008,0x0300,0x5701,0x0001,0x0010,0x0480,0x1008,
	0x0300,0x5701,0x0001,0x002b,0x0780,0x0009,0x0300,0x4a01,
	0x0004,0x0020,0x0780,0x1208,0x0300,0x5d01,0x0004,0x0030,
	0x0780,0x0209,0x0300,0x4c01,0x0004,0x0038,0x0780,0x0309,
	0x0300,0x4d01,0x0004,0x0048,0x0980,0x1108,0x0300,0x5a01,
	0xc005,0x0018,0x0980,0x0109,0x0300,0x4b01,0xc005,0x0028,
	0x0b80,0x020a,0x0000,0x6401,0x8006,0x0004,0x0c80,0x010b,
	0x0000,0xf201,0x8006,0x8002,0x0b80,0x020a,0x0000,0x6401,
	0x8006,0x0017,0x0c80,0x010b,0x0000,0xf201,0x8006,0x8015,
	0x0b80,0x020a,0x0000,0x6401,0x0007,0x0034,0x0c80,0x010b,
	0x0000,0xf201,0x0007,0x8032,0x0b80,0x020a,0x0000,0x6401,
	0x8006,0x803e,0x0c80,0x010b,0x0000,0xf201,0x8006,0x803d,
	0x0b80,0x100a,0x0000,0x6001,0x0007,0x0008,0x0b80,0x100a,
	0x0000,0x6001,0x0007,0x000b,0x0b80,0x100a,0x0000,0x6001,
	0x0007,0x001b,0x0b80,0x100a,0x0000,0x6001,0x0007,0x001e,
	0x0b80,0x100a,0x0000,0x6001,0x8007,0x0038,0x0b80,0x100a,
	0x0000,0x6001,0x8007,0x003b,0x0b80,0x100a,0x0000,0x6001,
	0x0007,0x8042,0x0b80,0x100a,0x0000,0x6001,0x0007,0x8045,
	0x0c80,0x000b,0x0000,0xf101,0x800b,0x8007,0x0c80,0x000b,
	0x0000,0xf101,0x800b,0x801a,0x0c80,0x000b,0x0000,0xf101,
	0x000c,0x8037,0x0c80,0x000b,0x0000,0xf101,0x800b,0x0042,
	0x0c80,0xd04b,0x0000,0xf301,0x8006,0x8009,0x0c80,0xd04b,
	0x0000,0xf301,0x8006,0x801c,0x0c80,0xd04b,0x0000,0xf301,
	0x8006,0x0044,0x0c80,0x030b,0x0000,0xf401,0x0008,0x0028,
	0x0c80,0x030b,0x0000,0xf401,0x0008,0x804b,0x0c00,0x040b,
	0x0000,0xf501,0x0008,0x8026
};

static const UINT16 level_data_01[0xcc] =
{
	0x0780,0x0209,0x0300,0x4c01,0x0004,0x0010,0x0780,0x0209,
	0x0300,0x4c01,0x4004,0x0020,0x0780,0x0309,0x0300,0x4d01,
	0xe003,0x0030,0x0780,0x0309,0x0300,0x4d01,0x8003,0x0040,
	0x0780,0x0209,0x0300,0x4c01,0x8004,0x0018,0x0780,0x0309,
	0x0300,0x4d01,0xc003,0x0028,0x0b80,0x000b,0x0000,0x0b02,
	0x8009,0x0029,0x0b80,0x0409,0x0000,0x0f02,0x8008,0x8028,
	0x0b80,0x040a,0x0000,0x3502,0x000a,0x8028,0x0b80,0x050a,
	0x0000,0x1002,0x8006,0x8028,0x0b80,0x120a,0x0000,0x3602,
	0x0008,0x004d,0x0b80,0x120a,0x0000,0x3602,0x0008,0x004f,
	0x0b80,0x120a,0x0000,0x3602,0x0008,0x0001,0x0b80,0x120a,
	0x0000,0x3602,0x0008,0x0003,0x0b80,0x130a,0x0000,0x3a02,
	0x0007,0x0023,0x0b80,0x130a,0x0000,0x3a02,0x0007,0x8025,
	0x0b80,0x130a,0x0000,0x3a02,0x8009,0x0023,0x0b80,0x130a,
	0x0000,0x3a02,0x8009,0x8025,0x0b80,0x140a,0x0000,0x3e02,
	0x0007,0x000d,0x0b80,0x140a,0x0000,0x3e02,0x0007,0x800f,
	0x0b80,0x000b,0x0000,0x0102,0x0007,0x804e,0x0b80,0xd24b,
	0x0000,0x0302,0x0007,0x000e,0x0b80,0x000b,0x0000,0x0402,
	0x8006,0x0020,0x0b80,0xd34b,0x0000,0x0502,0x8006,0x0024,
	0x0b80,0x000b,0x0000,0x0602,0x8009,0x0001,0x0b80,0xd44b,
	0x0000,0x0702,0x800b,0x800b,0x0b80,0xd54b,0x0000,0x0802,
	0x800b,0x000e,0x0b80,0x000b,0x0000,0x0902,0x800b,0x0010,
	0x0b80,0x000b,0x0000,0x0a02,0x0009,0x0024,0x0b80,0xd64b,
	0x0000,0x0c02,0x000c,0x8021,0x0b80,0x000b,0x0000,0x0d02,
	0x000c,0x0025,0x0b80,0x000b,0x0000,0x0e02,0x8009,0x004e,
	0x0b80,0x0609,0x0300,0x4e01,0x8006,0x8012,0x0b80,0x0609,
	0x0300,0x4e01,0x0007,0x8007
};

static const UINT16 level_data_02[0xcc] =
{
	0x0480,0x000b,0x0300,0x4501,0x0001,0x0018,0x0480,0x000b,
	0x0300,0x4501,0x2001,0x0030,0x0780,0x1208,0x0300,0x5d01,
	0x0004,0x0010,0x0780,0x1208,0x0300,0x5d01,0x2004,0x001c,
	0x0780,0x1208,0x0300,0x5d01,0xe003,0x0026,0x0780,0x1208,
	0x0300,0x5d01,0x8003,0x0034,0x0780,0x1208,0x0300,0x5d01,
	0x3004,0x0040,0x0780,0x010c,0x0300,0x4601,0x4004,0x0022,
	0x0780,0x010c,0x0300,0x4601,0x6004,0x0042,0x0780,0x000c,
	0x0500,0x7b01,0x800b,0x0008,0x0780,0x010c,0x0300,0x4601,
	0x2004,0x0008,0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,
	0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,
	0x0000,0xf001,0x0000,0x0000,0x0b80,0x000b,0x0000,0x1902,
	0x000b,0x0004,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x8003,
	0x0b80,0x000b,0x0000,0x1902,0x000b,0x000c,0x0b80,0x000b,
	0x0000,0x1a02,0x0009,0x800b,0x0b80,0x000b,0x0000,0x1902,
	0x000b,0x001c,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x801b,
	0x0b80,0x000b,0x0000,0x1902,0x000b,0x002c,0x0b80,0x000b,
	0x0000,0x1a02,0x0009,0x802b,0x0b80,0x000b,0x0000,0x1902,
	0x000b,0x0044,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x8043,
	0x0b80,0x000b,0x0000,0x1902,0x000b,0x004c,0x0b80,0x000b,
	0x0000,0x1a02,0x0009,0x804b,0x0b80,0x020c,0x0300,0x4801,
	0xa009,0x0010,0x0b80,0x020c,0x0300,0x4801,0xa009,0x0028,
	0x0b80,0x020c,0x0300,0x4801,0xa009,0x0036,0x0000,0x0000,
	0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,0x0000,0xf001,
	0x0000,0x0000,0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,
	0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,
	0x0000,0xf001,0x0000,0x0000
};

static const UINT16 level_data_03[0xcc] =
{
	0x0480,0x000b,0x0300,0x4501,0x0001,0x0018,0x0480,0x000b,
	0x0300,0x4501,0x2001,0x002b,0x0780,0x010c,0x0300,0x4601,
	0x0004,0x000d,0x0780,0x000c,0x0500,0x7b01,0x800b,0x0020,
	0x0780,0x010c,0x0300,0x4601,0x2004,0x0020,0x0780,0x010c,
	0x0300,0x4601,0x8003,0x0033,0x0780,0x010c,0x0300,0x4601,
	0x0004,0x003c,0x0780,0x010c,0x0300,0x4601,0xd003,0x0045,
	0x0780,0x000c,0x0500,0x7b01,0x900b,0x0041,0x0780,0x010c,
	0x0300,0x4601,0x3004,0x0041,0x0b80,0x020c,0x0300,0x4801,
	0x0007,0x0000,0x0b80,0x410a,0x0000,0x2b02,0xe006,0x4049,
	0x0b80,0x020c,0x0300,0x4801,0x8007,0x000b,0x0b80,0x000b,
	0x0000,0x2702,0x800a,0x8005,0x0b80,0x000b,0x0000,0x1e02,
	0x0008,0x800e,0x0b80,0x000b,0x0000,0x1f02,0x8007,0x0011,
	0x0b80,0x000b,0x0000,0x2802,0x000b,0x0012,0x0b80,0x000b,
	0x0000,0x2002,0x0007,0x8015,0x0b80,0x000b,0x0000,0x2102,
	0x0007,0x801b,0x0b80,0x000b,0x0000,0x2902,0x800a,0x001a,
	0x0b80,0x000b,0x0000,0x2202,0x8007,0x001e,0x0b80,0x000b,
	0x0000,0x1e02,0x0008,0x0025,0x0b80,0x000b,0x0000,0x2302,
	0x8007,0x802c,0x0b80,0x000b,0x0000,0x2802,0x000b,0x8028,
	0x0b80,0x020c,0x0300,0x4801,0x0007,0x0030,0x0b80,0x400a,
	0x0000,0x2e02,0x4007,0x002d,0x0b80,0x000b,0x0000,0x2702,
	0x800a,0x8035,0x0b80,0x020c,0x0300,0x4801,0x8007,0x0022,
	0x0b80,0x000b,0x0000,0x2402,0x8007,0x0047,0x0b80,0x000b,
	0x0000,0x2a02,0x800a,0x004b,0x0b80,0x000b,0x0000,0x2502,
	0x0007,0x804b,0x0b80,0x000b,0x0000,0x2602,0x0007,0x004e,
	0x0b80,0x020c,0x0300,0x4801,0x0007,0x8043,0x0b80,0x020c,
	0x0300,0x4801,0x8007,0x803d
};

static const UINT16 level_data_04[0xcc] =
{
	0x0780,0x0209,0x0300,0x4c01,0x0004,0x0010,0x0780,0x0209,
	0x0300,0x4c01,0x4004,0x0020,0x0780,0x0309,0x0300,0x4d01,
	0xe003,0x0030,0x0780,0x0309,0x0300,0x4d01,0x8003,0x0040,
	0x0780,0x0209,0x0300,0x4c01,0x8004,0x0018,0x0780,0x0309,
	0x0300,0x4d01,0xc003,0x0028,0x0780,0x000b,0x0300,0x5601,
	0x8004,0x0008,0x0780,0x000b,0x0300,0x5601,0x8004,0x0038,
	0x0780,0x000b,0x0300,0x5501,0x8004,0x0048,0x0980,0x0509,
	0x0f00,0x0f01,0x4005,0x4007,0x0980,0x0509,0x0f00,0x0f01,
	0x4005,0x4037,0x0b80,0x030a,0x0000,0x1302,0x8006,0x0040,
	0x0b80,0x110a,0x0000,0x1502,0x8008,0x8048,0x0b80,0x110a,
	0x0000,0x1502,0x8008,0x8049,0x0b80,0x000b,0x0000,0xf601,
	0x0007,0x8003,0x0b80,0x000b,0x0000,0xf701,0x0007,0x0005,
	0x0b80,0x000b,0x0000,0xf901,0x0007,0x8008,0x0b80,0x000b,
	0x0000,0xf901,0x0007,0x0010,0x0b80,0x000b,0x0000,0xfa01,
	0x0007,0x8013,0x0b80,0x000b,0x0000,0xf801,0x800b,0x800b,
	0x0b80,0x000b,0x0000,0x0002,0x800b,0x801a,0x0b80,0x000b,
	0x0000,0xf901,0x0007,0x8017,0x0b80,0x000b,0x0000,0xfa01,
	0x0007,0x001b,0x0b80,0x000b,0x0000,0xf801,0x800b,0x0013,
	0x0b80,0x000b,0x0000,0x4202,0x800b,0x0016,0x0b80,0x000b,
	0x0000,0xfb01,0x8007,0x8020,0x0b80,0x000b,0x0000,0xf601,
	0x0007,0x8023,0x0b80,0x000b,0x0000,0x4202,0x800b,0x800e,
	0x0b80,0x000b,0x0000,0x4302,0x800b,0x801d,0x0b80,0x000b,
	0x0000,0xf701,0x0007,0x0025,0x0b80,0x000b,0x0000,0xfd01,
	0x8006,0x003f,0x0b80,0x000b,0x0000,0xfe01,0x0007,0x0046,
	0x0b80,0x000b,0x0000,0xff01,0x8007,0x8049,0x0b80,0x000b,
	0x0000,0xfc01,0x8009,0x0042
};

static const UINT16 level_data_05[0xcc] =
{
	0x0480,0x1008,0x0300,0x5701,0x0001,0x0010,0x0480,0x1008,
	0x0300,0x5701,0x0001,0x002b,0x0780,0x0009,0x0300,0x4a01,
	0x0004,0x0020,0x0780,0x1208,0x0300,0x5d01,0x0004,0x0030,
	0x0780,0x0209,0x0300,0x4c01,0x0004,0x0038,0x0780,0x0309,
	0x0300,0x4d01,0x0004,0x0048,0x0980,0x1108,0x0300,0x5a01,
	0xc005,0x0018,0x0980,0x0109,0x0300,0x4b01,0xc005,0x0028,
	0x0b80,0x020a,0x0000,0x6401,0x8006,0x0004,0x0c80,0x010b,
	0x0000,0xf201,0x8006,0x8002,0x0b80,0x020a,0x0000,0x6401,
	0x8006,0x0017,0x0c80,0x010b,0x0000,0xf201,0x8006,0x8015,
	0x0b80,0x020a,0x0000,0x6401,0x0007,0x0034,0x0c80,0x010b,
	0x0000,0xf201,0x0007,0x8032,0x0b80,0x020a,0x0000,0x6401,
	0x8006,0x803e,0x0c80,0x010b,0x0000,0xf201,0x8006,0x803d,
	0x0b80,0x100a,0x0000,0x6001,0x0007,0x0008,0x0b80,0x100a,
	0x0000,0x6001,0x0007,0x000b,0x0b80,0x100a,0x0000,0x6001,
	0x0007,0x001b,0x0b80,0x100a,0x0000,0x6001,0x0007,0x001e,
	0x0b80,0x100a,0x0000,0x6001,0x8007,0x0038,0x0b80,0x100a,
	0x0000,0x6001,0x8007,0x003b,0x0b80,0x100a,0x0000,0x6001,
	0x0007,0x8042,0x0b80,0x100a,0x0000,0x6001,0x0007,0x8045,
	0x0c80,0x000b,0x0000,0xf101,0x800b,0x8007,0x0c80,0x000b,
	0x0000,0xf101,0x800b,0x801a,0x0c80,0x000b,0x0000,0xf101,
	0x000c,0x8037,0x0c80,0x000b,0x0000,0xf101,0x800b,0x0042,
	0x0c80,0xd04b,0x0000,0xf301,0x8006,0x8009,0x0c80,0xd04b,
	0x0000,0xf301,0x8006,0x801c,0x0c80,0xd04b,0x0000,0xf301,
	0x8006,0x0044,0x0c80,0x030b,0x0000,0xf401,0x0008,0x0028,
	0x0c80,0x030b,0x0000,0xf401,0x0008,0x804b,0x0c00,0x040b,
	0x0000,0xf501,0x0008,0x8026
};

static const UINT16 level_data_06[0xcc] =
{
	0x0000,0x1008,0x0300,0x5701,0x0001,0x0010,0x0000,0x1008,
	0x0300,0x5701,0x0001,0x002b,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0700,0x0009,0x0300,0x4a01,0x0004,0x0020,
	0x0700,0x1208,0x0300,0x5d01,0x0004,0x0030,0x0700,0x0209,
	0x0300,0x4c01,0x0004,0x0038,0x0700,0x0309,0x0300,0x4d01,
	0x0004,0x0048,0x0900,0x1108,0x0300,0x5a01,0xc005,0x0018,
	0x0900,0x0109,0x0300,0x4b01,0xc005,0x0028,0x0000,0x000b,
	0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,
	0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,
	0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,
	0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,
	0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,
	0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,
	0x0000,0x0000,0x0018,0x0000,0x0980,0xdb4c,0x0000,0x3202,
	0x0006,0x0004,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8002,
	0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8003,0x0b80,0x0609,
	0x0300,0x4e01,0x5006,0x8004,0x0b80,0x0609,0x0300,0x4e01,
	0x5006,0x0008,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0010,
	0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0012,0x0b80,0x0609,
	0x0300,0x4e01,0x5006,0x0014,0x0b80,0x0609,0x0300,0x4e01,
	0x5006,0x0016,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0018,
	0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0020,0x0b80,0x0609,
	0x0300,0x4e01,0x5006,0x0023,0x0b80,0x0609,0x0300,0x4e01,
	0x5006,0x0030,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0038,
	0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0040,0x0b80,0x0609,
	0x0300,0x4e01,0x5006,0x0042
};

static const UINT16 *const level_data_lookup[] =
{
	level_data_00,
	level_data_01,
	level_data_02,
	level_data_03,
	level_data_04,
	level_data_05,
	level_data_06,
};

static void AccessLevelDataCommand()
{
	// Level data command
	if (CurrentCmd==0xf5)
	{
		INT32 level=CChipRam[0x1b];
		const UINT16* level_data=level_data_lookup[level];
		INT32 i=0;
		for (i=0; i<0xcc; i++)
		{
			CChipRam[0x200 + i*2 + 0]=level_data[i]>>8;
			CChipRam[0x200 + i*2 + 1]=level_data[i]&0xff;
		}

		// The bootleg cchip writes 0 to these locations - hard to tell what the real one writes
		CChipRam[0x0]=0;
		CChipRam[0x76]=0;
		CChipRam[0x75]=0;
		CChipRam[0x74]=0;
		CChipRam[0x72]=0;
		CChipRam[0x71]=0;
		CChipRam[0x70]=0;
		CChipRam[0x66]=0;
		CChipRam[0x2b]=0;
		CChipRam[0x30]=0;
		CChipRam[0x31]=0;
		CChipRam[0x32]=0;
		CChipRam[0x27]=0;
		c588=0;
		c589=0;
		c58a=0;

		CChipRam[0x1a]=0;
		CChipRam[0x7a]=1; // Signal command complete
	}

	CurrentCmd=0;
}

static void updateDifficulty(INT32 Mode)
{
	// The game is made up of 6 rounds, when you complete the
	// sixth you return to the start but with harder difficulty.
	if (Mode == 0)
	{
		switch (CChipRam[0x15]&3) // Dipswitch B
		{
		case 3:
			CChipRam[0x2c]=0x31;
			CChipRam[0x77]=0x05;
			CChipRam[0x25]=0x0f;
			CChipRam[0x26]=0x0b;
			break;
		case 0:
			CChipRam[0x2c]=0x20;
			CChipRam[0x77]=0x06;
			CChipRam[0x25]=0x07;
			CChipRam[0x26]=0x03;
			break;
		case 1:
			CChipRam[0x2c]=0x31;
			CChipRam[0x77]=0x05;
			CChipRam[0x25]=0x0f;
			CChipRam[0x26]=0x0b;
			break;
		case 2:
			CChipRam[0x2c]=0x3c;
			CChipRam[0x77]=0x04;
			CChipRam[0x25]=0x13;
			CChipRam[0x26]=0x0f;
			break;
		}
	}
	else
	{
		switch (CChipRam[0x15]&3) // Dipswitch B
		{
		case 3:
			CChipRam[0x2c]=0x46;
			CChipRam[0x77]=0x05;
			CChipRam[0x25]=0x11;
			CChipRam[0x26]=0x0e;
			break;
		case 0:
			CChipRam[0x2c]=0x30;
			CChipRam[0x77]=0x06;
			CChipRam[0x25]=0x0b;
			CChipRam[0x26]=0x03;
			break;
		case 1:
			CChipRam[0x2c]=0x3a;
			CChipRam[0x77]=0x05;
			CChipRam[0x25]=0x0f;
			CChipRam[0x26]=0x09;
			break;
		case 2:
			CChipRam[0x2c]=0x4c;
			CChipRam[0x77]=0x04;
			CChipRam[0x25]=0x19;
			CChipRam[0x26]=0x11;
			break;
		};
	}
}

void OpwolfCChipUpdate(UINT8 Input1, UINT8 Input2)
{
	// Update input ports, these are used by both the 68k directly and by the c-chip
	CChipRam[0x4] = Input1;
	CChipRam[0x5] = Input2;

	// Coin slots
	if (CChipRam[0x4]!=CChipLast_04)
	{
		INT32 slot=-1;

		if (CChipRam[0x4]&1) slot=0;
		if (CChipRam[0x4]&2) slot=1;

		if (slot != -1)
		{
			CChipCoins[slot]++;
			if (CChipCoins[slot] >= CChipCoinsForCredit[slot])
			{
				CChipRam[0x53]+=CChipCreditsForCoin[slot];
				CChipRam[0x51]=0x55;
				CChipRam[0x52]=0x55;
				CChipCoins[slot]-=CChipCoinsForCredit[slot];
			}
		}

		if (CChipRam[0x53]>9)
			CChipRam[0x53]=9;
	}
	CChipLast_04=CChipRam[0x4];

	// Service switch
	if (CChipRam[0x5]!=CChipLast_05)
	{
		if ((CChipRam[0x5]&4)==0)
		{
			CChipRam[0x53]++;
			CChipRam[0x51]=0x55;
			CChipRam[0x52]=0x55;
		}
	}
	CChipLast_05=CChipRam[0x5];

	// Special handling for last level
	if (CChipRam[0x1b]==0x6)
	{
		// Check for triggering final helicopter (end boss)
		if (c58a==0)
		{
			if ((CChipRam[0x72]&0x7f) >= 8 && CChipRam[0x74]==0 && CChipRam[0x1c]==0 && CChipRam[0x1d]==0 && CChipRam[0x1f]==0)
			{
				CChipRam[0x30]=1;
				CChipRam[0x74]=1;
				c58a=1;
			}
		}

		if (CChipRam[0x1a]==0x90)
			CChipRam[0x74]=0;

		if (c58a!=0)
		{
			if (c589==0 && CChipRam[0x27]==0 && CChipRam[0x75]==0 && CChipRam[0x1c]==0 && CChipRam[0x1d]==0 && CChipRam[0x1e]==0 && CChipRam[0x1f]==0)
			{
				CChipRam[0x31]=1;
				CChipRam[0x75]=1;
				c589=1;
			}
		}

		if (CChipRam[0x2b]==0x1)
		{
			CChipRam[0x2b]=0;

			if (CChipRam[0x30]==0x1)
			{
				if (CChipRam[0x1a]!=0x90)
					CChipRam[0x1a]--;
			}

			if (CChipRam[0x72]==0x9)
			{
				if (CChipRam[0x76]!=0x4)
				{
					CChipRam[0x76]=3;
				}
			}
			else
			{
				// This timer is derived from the bootleg rather than the real board, I'm not 100% sure about it
				c588|=0x80;

				CChipRam[0x72]=c588;
				c588++;

				CChipRam[0x1a]--;
				CChipRam[0x1a]--;
				CChipRam[0x1a]--;
			}
		}

		// Update difficulty settings
		if (CChipRam[0x76]==0)
		{
			CChipRam[0x76]=1;
			updateDifficulty(1);
		}
	}

	// These variables are cleared every frame during attract mode and the intro.
	if (CChipRam[0x34] < 2)
	{
		updateDifficulty(0);
		CChipRam[0x76]=0;
		CChipRam[0x75]=0;
		CChipRam[0x74]=0;
		CChipRam[0x72]=0;
		CChipRam[0x71]=0;
		CChipRam[0x70]=0;
		CChipRam[0x66]=0;
		CChipRam[0x2b]=0;
		CChipRam[0x30]=0;
		CChipRam[0x31]=0;
		CChipRam[0x32]=0;
		CChipRam[0x27]=0;
		c588=0;
		c589=0;
		c58a=0;
	}

	// Check for level completion (all enemies destroyed)
	if (CChipRam[0x1c] == 0 && CChipRam[0x1d] == 0 && CChipRam[0x1e] == 0 && CChipRam[0x1f] == 0 && CChipRam[0x20] == 0)
	{
		// Special handling for end of level 6
		if (CChipRam[0x1b]==0x6)
		{
			// Don't signal end of level until final boss is destroyed
			if (CChipRam[0x27]==0x1)
				CChipRam[0x32]=1;
		}
		else
		{
			// Signal end of level
			CChipRam[0x32]=1;
		}
	}

	if (CChipRam[0xe] == 1)
	{
		CChipRam[0xe]=0xfd;
		CChipRam[0x61]=0x04;
	}

	// Access level data command (address 0xf5 goes from 1 -> 0)
	if (CChipRam[0x7a]==0 && CChipLast_7a!=0 && CurrentCmd!=0xf5)
	{
		// Simulate time for command to execute (exact timing unknown, this is close)
		CurrentCmd=0xf5;
		bprintf(PRINT_NORMAL, _T("Accessing Level Data Command\n"));
		AccessLevelDataCommand();
//		timer_set(ATTOTIME_IN_CYCLES(80000,0), NULL, 0, opwolf_timer_callback);
	}
	CChipLast_7a=CChipRam[0x7a];

	// This seems to some kind of periodic counter - results are expected
	// by the 68k when the counter reaches 0xa
	if (CChipRam[0x7f]==0xa)
	{
		CChipRam[0xfe]=0xf7;
		CChipRam[0xff]=0x6e;
	}

	// These are set every frame
	CChipRam[0x64]=0;
	CChipRam[0x66]=0;
}

UINT16 OpwolfCChipStatusRead()
{
	return 0x01;
}

UINT16 OpwolfCChipDataRead(UINT32 Offset)
{
	return CChipRam[(CurrentBank * 0x400) + Offset];
}

void OpwolfCChipStatusWrite()
{
	CChipRam[0x3d] = 1;
	CChipRam[0x7a] = 1;
	updateDifficulty(0);
}

void OpwolfCChipBankWrite(UINT16 Data)
{
	CurrentBank = Data & 7;
}

void OpwolfCChipDataWrite(UINT8 *p68kRom, UINT32 Offset, UINT16 Data )
{
	CChipRam[(CurrentBank * 0x400) + Offset] = Data & 0xff;

	if (CurrentBank == 0) {
		if (Offset == 0x14)
		{
			UINT16* rom = (UINT16*)p68kRom;
			UINT32 CoinTable[2]= { 0, 0};
			UINT8 CoinOffset[2];
			INT32 Slot;

			if ((CChipRegion == OPWOLF_REGION_JAPAN) || (CChipRegion == OPWOLF_REGION_US)) {
				CoinTable[0] = 0x03ffce;
				CoinTable[1] = 0x03ffce;
			}
			if ((CChipRegion == OPWOLF_REGION_WORLD) || (CChipRegion == OPWOLF_REGION_OTHER)) {
				CoinTable[0] = 0x03ffde;
				CoinTable[1] = 0x03ffee;
			}
			
			CoinOffset[0] = 12 - (4 * ((Data & 0x30) >> 4));
			CoinOffset[1] = 12 - (4 * ((Data & 0xc0) >> 6));

			for (Slot = 0; Slot < 2; Slot++) {
				if (CoinTable[Slot]) {
					CChipCoinsForCredit[Slot] = rom[(CoinTable[Slot] + CoinOffset[Slot] + 0) / 2] & 0xff;
					CChipCreditsForCoin[Slot] = rom[(CoinTable[Slot] + CoinOffset[Slot] + 2) / 2] & 0xff;
				}
			}
		}

		// Dip switch B
		if (Offset == 0x15) {
			updateDifficulty(0);
		}
	}
}

void OpwolfCChipReset()
{
	memset(CChipRam, 0, 0x400 * 8);
	
	CChipLast_7a = 0;
	CChipLast_04 = 0xfc;
	CChipLast_05 = 0xff;
	CChipCoins[0] = 0;
	CChipCoins[1] = 0;
	CChipCoinsForCredit[0] = 1;
	CChipCreditsForCoin[0] = 1;
	CChipCoinsForCredit[1] = 1;
	CChipCreditsForCoin[1] = 1;
	CurrentBank = 0;
	CurrentCmd = 0;
	c588 = 0;
	c589 = 0;
	c58a = 0;
	
}

void OpwolfCChipInit(INT32 Region)
{
	CChipRegion = Region;
	
	CChipRam = (UINT8*)BurnMalloc(0x400 * 8);
	memset(CChipRam, 0, 0x400 * 8);
	
	CChipLast_7a = 0;
	CChipLast_04 = 0xfc;
	CChipLast_05 = 0xff;
	CChipCoins[0] = 0;
	CChipCoins[1] = 0;
	CChipCoinsForCredit[0] = 1;
	CChipCreditsForCoin[0] = 1;
	CChipCoinsForCredit[1] = 1;
	CChipCreditsForCoin[1] = 1;
	
	TaitoIC_OpwolfCChipInUse = 1;
}

void OpwolfCChipExit()
{
	BurnFree(CChipRam);
	
	CChipRegion = 0;
	
	CChipLast_7a = 0;
	CChipLast_04 = 0;
	CChipLast_05 = 0;
	CChipCoins[0] = 0;
	CChipCoins[1] = 0;
	CChipCoinsForCredit[0] = 0;
	CChipCreditsForCoin[0] = 0;
	CChipCoinsForCredit[1] = 0;
	CChipCreditsForCoin[1] = 0;
	CurrentBank = 0;
	CurrentCmd = 0;
	c588 = 0;
	c589 = 0;
	c58a = 0;
	
}

void OpwolfCChipScan(INT32 nAction)
{
	struct BurnArea ba;
	
	if (nAction & ACB_MEMORY_RAM) {
		memset(&ba, 0, sizeof(ba));
		ba.Data	  = CChipRam;
		ba.nLen	  = 0x400 * 8;
		ba.szName = "C-Chip Ram";
		BurnAcb(&ba);
	}
	
	if (nAction & ACB_DRIVER_DATA) {
		SCAN_VAR(CurrentBank);
		SCAN_VAR(CurrentCmd);
		SCAN_VAR(CChipLast_7a);
		SCAN_VAR(CChipLast_04);
		SCAN_VAR(CChipLast_05);
		SCAN_VAR(CChipCoinsForCredit);
		SCAN_VAR(CChipCreditsForCoin);
		SCAN_VAR(CChipCoins);
		SCAN_VAR(c588);
		SCAN_VAR(c589);
		SCAN_VAR(c58a);
	}
}

#undef OPWOLF_REGION_JAPAN
#undef OPWOLF_REGION_US
#undef OPWOLF_REGION_WORLD
#undef OPWOLF_REGION_OTHER


/*************************************************************************

  Bonze Adventure C-Chip
  ======================

  Based on RAINE. Improvements with a lot of help from Ruben Panossian.
  Additional thanks to Robert Gallagher and stephh.

  Verification on real hardware by Bryan McPhail, Feb 2006:
    The restart positions on real hardware are affected by the level
    variable, as well as scroll & player position.  The old implementation
    did not account for this and so overlapping map positions between
    levels reported the wrong data.

    Restart data is confirmed correct & complete.  Previously many
    restart points were missed.

    Mapping of restart positions now accurate to the real hardware -
    previously these values were approximated by hand (and many
    missing).

  Taken from MAME 0.136 Jan 11, 2010

*************************************************************************/


static INT32 current_round = 0;
static INT32 current_bank = 0;
static INT32 coin_lockout = 0;

static UINT8 cval[26];
static UINT8 cc_port;
static UINT8 restart_status;

struct cchip_mapping
{
	UINT16 xmin;
	UINT16 xmax;
	UINT16 ymin;
	UINT16 ymax;
	UINT16 sx;
	UINT16 sy;
	UINT16 px;
	UINT16 py;
};

static const UINT16 CLEV[][13] =
{
/*    map start       player start    player y-range  player x-range  map y-range     map x-range     time   */
	{ 0x0000, 0x0018, 0x0020, 0x0030, 0x0028, 0x00D0, 0x0050, 0x0090, 0x0000, 0x0118, 0x0000, 0x0C90, 0x3800 },
	{ 0x0000, 0x0100, 0x0048, 0x0028, 0x0028, 0x0090, 0x0070, 0x00B0, 0x0000, 0x02C0, 0x0000, 0x0CA0, 0x3000 },
	{ 0x0000, 0x0518, 0x0068, 0x00B8, 0x0028, 0x00D0, 0x0068, 0x00B0, 0x02F8, 0x0518, 0x0000, 0x0EF8, 0x3000 },
	{ 0x0978, 0x0608, 0x00C8, 0x00B0, 0x0028, 0x00D0, 0x0098, 0x00C8, 0x0608, 0x06E8, 0x0000, 0x0A48, 0x2000 },
	{ 0x0410, 0x0708, 0x0070, 0x0030, 0x0028, 0x00D0, 0x0060, 0x0090, 0x0708, 0x0708, 0x0410, 0x1070, 0x3800 },
	{ 0x1288, 0x0808, 0x0099, 0x00CE, 0x0028, 0x00D0, 0x0060, 0x00C0, 0x0000, 0x0808, 0x1288, 0x1770, 0x3000 },
	{ 0x11B0, 0x0908, 0x0118, 0x0040, 0x0028, 0x00D0, 0x00B0, 0x00C0, 0x0900, 0x0910, 0x0050, 0x11B0, 0x3800 },
	{ 0x0000, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x0000, 0x0398, 0x1000 },
	{ 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0x8800 },
	{ 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0xffff },
	{ 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0xffff },
};

static const struct cchip_mapping level00[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0x0200, 0x0000, 0x0100,	0x0000, 0x0018, 0x0020, 0x00a8 },
	{ 0x0200, 0x0380, 0x0000, 0x0100,	0x01e0, 0x0018, 0x0070, 0x0098 },
	{ 0x0380, 0x0620, 0x0000, 0x0100,	0x04a0, 0x0018, 0x0070, 0x0090 },
	{ 0x0620, 0x08f0, 0x0000, 0x0100,	0x06b8, 0x0018, 0x0078, 0x0078 },
	{ 0x08f0, 0x0a20, 0x0000, 0x0100,	0x08c8, 0x0018, 0x0070, 0x0028 },
	{ 0x0a20, 0x0c80, 0x0000, 0x0100,	0x0a68, 0x0018, 0x0070, 0x0058 },
	{ 0x0c80, 0x0e00, 0x0000, 0x0100,	0x0c40, 0x0018, 0x0070, 0x0040 },

	{ 0x0380, 0x07c0, 0x0100, 0x0200,	0x0038, 0x0418, 0x0070, 0x00a8 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level01[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0x0120, 0x0100, 0x0200,	0x0000, 0x0208, 0x0040, 0x0070 },

	{ 0x0000, 0x0120, 0x0200, 0x0300,	0x0000, 0x0208, 0x0040, 0x0070 },
	{ 0x0120, 0x0460, 0x0200, 0x0300,	0x0080, 0x0218, 0x00b0, 0x0080 },
	{ 0x0460, 0x0690, 0x0200, 0x0278,	0x0450, 0x01f8, 0x0090, 0x0030 },
	{ 0x0460, 0x0690, 0x0278, 0x0300,	0x0450, 0x0218, 0x00a0, 0x00a0 },
	{ 0x0690, 0x07d0, 0x0200, 0x0278,	0x0618, 0x01f8, 0x00a0, 0x0040 },
	{ 0x0690, 0x07d0, 0x0278, 0x0300,	0x0628, 0x0218, 0x00a8, 0x00b0 },
	{ 0x07d0, 0x08b0, 0x0200, 0x0300,	0x07a8, 0x0218, 0x0090, 0x0060 },
	{ 0x08b0, 0x09d0, 0x0200, 0x0300,	0x0840, 0x0218, 0x0088, 0x0060 },
	{ 0x09d0, 0x0b00, 0x0200, 0x0300,	0x0958, 0x0218, 0x00a0, 0x0070 },
	{ 0x0b00, 0x0c90, 0x0200, 0x0300,	0x0a98, 0x0218, 0x0088, 0x0050 },
	{ 0x0c90, 0x0e00, 0x0200, 0x0300,	0x0c20, 0x0200, 0x00a0, 0x0028 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level02[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0x01c0, 0x04f4, 0x05f8,	0x0000, 0x0518, 0x0068, 0x00b0 },
	{ 0x01c0, 0x03c0, 0x04f4, 0x05f8,	0x00d0, 0x0518, 0x0078, 0x0060 },
	{ 0x03c0, 0x06e0, 0x04f4, 0x05f8,	0x02f0, 0x0518, 0x0078, 0x0048 },
	{ 0x06e0, 0x0840, 0x04f4, 0x05f8,	0x0670, 0x0518, 0x0078, 0x0048 },
	{ 0x0840, 0x0a10, 0x04f4, 0x05f8,	0x07d8, 0x0518, 0x0070, 0x0060 },
	{ 0x0a10, 0x0b80, 0x04f4, 0x05f8,	0x09e8, 0x0500, 0x0080, 0x0080 },
	{ 0x0b80, 0x1090, 0x04f4, 0x05f8,	0x0b20, 0x0418, 0x0070, 0x0080 },

	{ 0x0230, 0x03a0, 0x040c, 0x04f4,	0x02e8, 0x04b0, 0x0080, 0x0090 },
	{ 0x03a0, 0x03b0, 0x040c, 0x04f4,	0x0278, 0x0318, 0x0078, 0x00a8 },
	{ 0x0520, 0x08e0, 0x040c, 0x04f4,	0x0608, 0x0318, 0x0080, 0x0058 },
	{ 0x08e0, 0x0a00, 0x040c, 0x04f4,	0x0878, 0x0318, 0x0078, 0x0098 },

	{ 0x0230, 0x03b0, 0x02f8, 0x040c,	0x0278, 0x0318, 0x0078, 0x00a8 },
	{ 0x03b0, 0x0520, 0x02f8, 0x040c,	0x0390, 0x0318, 0x0070, 0x00b8 },
	{ 0x0520, 0x08e0, 0x02f8, 0x040c,	0x0608, 0x0318, 0x0080, 0x0058 },
	{ 0x08e0, 0x0a00, 0x02f8, 0x040c,	0x0878, 0x0318, 0x0078, 0x0098 }
};

static const struct cchip_mapping level03[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0x0280, 0x0618, 0x06f8,	0x00d8, 0x0608, 0x00b8, 0x00a0 },
	{ 0x0280, 0x0380, 0x0618, 0x06f8,	0x02b0, 0x0608, 0x00b8, 0x0090 },
	{ 0x0380, 0x0620, 0x0618, 0x06f8,	0x02c8, 0x0608, 0x00c0, 0x0090 },
	{ 0x0620, 0x0760, 0x0618, 0x06f8,	0x0630, 0x0608, 0x00c0, 0x0028 },
	{ 0x0760, 0x0910, 0x0618, 0x06f8,	0x07e8, 0x0608, 0x00b8, 0x0078 },
	{ 0x0910, 0x0a30, 0x0618, 0x06f8,	0x0930, 0x0608, 0x00b8, 0x0080 },
	{ 0x0a30, 0x0b60, 0x0618, 0x06f8,	0x0a48, 0x0608, 0x00c0, 0x0068 },

	{ 0x0090, 0x01d0, 0x06f8, 0x07f8,	0x0020, 0x0610, 0x00b8, 0x00a8 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level04[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0390, 0x06a0, 0x0704, 0x0804,	0x0560, 0x0708, 0x0068, 0x0090 },
	{ 0x06a0, 0x0850, 0x0704, 0x0804,	0x0600, 0x0708, 0x0080, 0x0070 },
	{ 0x0850, 0x09e0, 0x0704, 0x0804,	0x0860, 0x0708, 0x0060, 0x0090 },
	{ 0x09e0, 0x0c00, 0x0704, 0x0804,	0x09c0, 0x0708, 0x0068, 0x0080 },
	{ 0x0c00, 0x0da0, 0x0704, 0x0804,	0x0c58, 0x0708, 0x0068, 0x0070 },
	{ 0x0da0, 0x0f80, 0x0704, 0x0804,	0x0d80, 0x0708, 0x0070, 0x00b0 },
	{ 0x0f80, 0x1080, 0x0704, 0x0804,	0x0ea8, 0x0708, 0x0070, 0x00b0 },
	{ 0x1080, 0x1230, 0x0704, 0x0804,	0x0fc0, 0x0708, 0x0080, 0x0030 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level05[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x1280, 0x1370, 0x800, 0x900,		0x1288, 0x0808, 0x0099, 0x00ce },
	{ 0x1370, 0x14e0, 0x800, 0x900,		0x12f0, 0x0808, 0x0078, 0x0028 },
	{ 0x14e0, 0x1660, 0x800, 0x900,		0x1488, 0x0808, 0x0080, 0x0070 },
	{ 0x1660, 0x18f0, 0x800, 0x900,		0x1600, 0x0808, 0x0080, 0x0090 },

	{ 0x1480, 0x1640, 0x6f8, 0x800,		0x1508, 0x0708, 0x0080, 0x0090 },
	{ 0x1640, 0x1760, 0x6f8, 0x800,		0x16e8, 0x06f0, 0x0080, 0x0058 },
	{ 0x1760, 0x1900, 0x6f8, 0x800,		0x1770, 0x0728, 0x0080, 0x0080 },

	{ 0x14e0, 0x1570, 0x6a0, 0x6f8,		0x1508, 0x05e8, 0x0040, 0x0088 },
	{ 0x1570, 0x1680, 0x6a0, 0x6f8,		0x1568, 0x0608, 0x0080, 0x0090 },
	{ 0x1680, 0x1770, 0x6a0, 0x6f8,		0x1640, 0x05e8, 0x0088, 0x0088 },
	{ 0x1770, 0x18d0, 0x6a0, 0x6f8,		0x1770, 0x0650, 0x00d8, 0x0070 },

	{ 0x14e0, 0x1570, 0x664, 0x6a0,		0x1508, 0x05e8, 0x0040, 0x0088 },
	{ 0x1570, 0x1680, 0x664, 0x6a0,		0x1578, 0x05d0, 0x0098, 0x0060 },
	{ 0x1680, 0x1770, 0x664, 0x6a0,		0x1640, 0x05e8, 0x0088, 0x0088 },
	{ 0x1770, 0x18d0, 0x664, 0x6a0,		0x1770, 0x0650, 0x00d8, 0x0070 },

	{ 0x14e0, 0x1570, 0x624, 0x664,		0x1508, 0x05e8, 0x0040, 0x0088 },
	{ 0x1570, 0x1680, 0x624, 0x664,		0x1578, 0x05d0, 0x0098, 0x0060 },
	{ 0x1680, 0x1770, 0x624, 0x664,		0x1640, 0x05e8, 0x0088, 0x0088 },
	{ 0x1770, 0x18d0, 0x624, 0x664,		0x1770, 0x0588, 0x0090, 0x0088 },

	{ 0x14e0, 0x1570, 0x5d4, 0x624,		0x1508, 0x05e8, 0x0040, 0x0088 },
	{ 0x1570, 0x1680, 0x5d4, 0x624,		0x1578, 0x05d0, 0x0098, 0x0060 },
	{ 0x1680, 0x16a0, 0x5d4, 0x624,		0x1630, 0x0528, 0x0088, 0x0088 },
	{ 0x16a0, 0x1770, 0x5d4, 0x624,		0x1658, 0x0528, 0x0088, 0x0088 },
	{ 0x1770, 0x18d0, 0x5d4, 0x624,		0x1770, 0x0588, 0x0090, 0x0088 },

	{ 0x14e0, 0x15d0, 0x5a4, 0x5d4,		0x1508, 0x0580, 0x0040, 0x0080 },
	{ 0x15d0, 0x15f0, 0x5a4, 0x5d4,		0x1508, 0x04f8, 0x0080, 0x0060 },
	{ 0x15f0, 0x1630, 0x5a4, 0x5d4,		0x1580, 0x04f8, 0x0068, 0x0080 },
	{ 0x1630, 0x16a0, 0x5a4, 0x5d4,		0x1630, 0x0530, 0x0088, 0x0080 },
	{ 0x16a0, 0x17b0, 0x5a4, 0x5d4,		0x1658, 0x0528, 0x0088, 0x0088 },
	{ 0x17b0, 0x18c0, 0x5a4, 0x5d4,		0x1770, 0x0508, 0x0098, 0x0088 },

	{ 0x14e0, 0x15f0, 0x4f8, 0x5a4,		0x1508, 0x04f8, 0x0080, 0x0060 },
	{ 0x15f0, 0x1670, 0x4f8, 0x5a4,		0x15c8, 0x0548, 0x00a8, 0x0070 },
	{ 0x1670, 0x1750, 0x4f8, 0x5a4,		0x1680, 0x0528, 0x00a8, 0x0070 },
	{ 0x1750, 0x18d0, 0x4f8, 0x5a4,		0x1770, 0x04a0, 0x00a8, 0x0078 },

	{ 0x14e0, 0x1630, 0x478, 0x4f8,		0x1508, 0x04f8, 0x0080, 0x0060 },
	{ 0x1630, 0x16b0, 0x478, 0x4f8,		0x15d0, 0x0440, 0x00b8, 0x0078 },
	{ 0x16b0, 0x1760, 0x478, 0x4f8,		0x1660, 0x0460, 0x0080, 0x0060 },
	{ 0x1760, 0x17f0, 0x478, 0x4f8,		0x1738, 0x0420, 0x0090, 0x0070 },
	{ 0x17f0, 0x18d0, 0x478, 0x4f8,		0x1770, 0x0450, 0x00d8, 0x0060 },

	{ 0x14e0, 0x16d0, 0x3f8, 0x478,		0x1500, 0x03e8, 0x0090, 0x0058 },
	{ 0x16d0, 0x17f0, 0x3f8, 0x478,		0x16e0, 0x0398, 0x0068, 0x0068 },
	{ 0x17f0, 0x18d0, 0x3f8, 0x478,		0x1770, 0x0450, 0x00d8, 0x0060 },

	{ 0x14e0, 0x1610, 0x35c, 0x3f8,		0x1518, 0x0368, 0x0090, 0x0058 },
	{ 0x1610, 0x16b0, 0x35c, 0x3f8,		0x15b0, 0x0340, 0x0098, 0x0058 },
	{ 0x16b0, 0x17e0, 0x35c, 0x3f8,		0x1728, 0x0320, 0x0068, 0x0068 },
	{ 0x17e0, 0x18d0, 0x35c, 0x3f8,		0x1770, 0x0330, 0x00c0, 0x0080 },

	{ 0x14e0, 0x1650, 0x2f8, 0x35c,		0x1518, 0x0368, 0x0090, 0x0058 },
	{ 0x1650, 0x17d0, 0x2f8, 0x35c,		0x1630, 0x02b0, 0x0088, 0x0060 },
	{ 0x17d0, 0x18d0, 0x2f8, 0x35c,		0x1740, 0x02a8, 0x0090, 0x0058 },

	{ 0x14e0, 0x1650, 0x268, 0x2f8,		0x15a8, 0x0268, 0x0080, 0x0058 },
	{ 0x1650, 0x17b0, 0x268, 0x2f8,		0x1650, 0x0250, 0x0080, 0x0058 },
	{ 0x17b0, 0x18d0, 0x268, 0x2f8,		0x1740, 0x02a8, 0x0090, 0x0058 },

	{ 0x14e0, 0x15f0, 0x1d8, 0x268,		0x1508, 0x0208, 0x0078, 0x0060 },
	{ 0x15f0, 0x17b0, 0x1d8, 0x268,		0x16c8, 0x0178, 0x0080, 0x0060 },
	{ 0x17b0, 0x18d0, 0x1d8, 0x268,		0x1740, 0x02a8, 0x0090, 0x0058 },

	{ 0x14e0, 0x18d0, 0x158, 0x1d8,		0x1610, 0x0110, 0x0078, 0x0068 },
	{ 0x14e0, 0x18d0, 0x158, 0x1d8,		0x1610, 0x0110, 0x0078, 0x0068 },

	{ 0x14d0, 0x18d0, 0x15c, 0x19c,		0x1618, 0x0110, 0x0078, 0x0068 },
	{ 0x14d0, 0x15b0, 0x19c, 0x1bc,		0x1618, 0x0110, 0x0078, 0x0068 },
	{ 0x15b0, 0x1670, 0x19c, 0x1bc,		0x1580, 0x0128, 0x0070, 0x0080 },
	{ 0x1670, 0x18d0, 0x19c, 0x1bc,		0x1618, 0x0110, 0x0078, 0x0068 },
	{ 0x14d0, 0x14f0, 0x1bc, 0x1dc,		0x1618, 0x0110, 0x0078, 0x0068 },
	{ 0x14f0, 0x15f0, 0x1bc, 0x1dc,		0x1508, 0x0208, 0x0078, 0x0060 },
	{ 0x15f0, 0x1670, 0x1bc, 0x1dc,		0x1580, 0x0128, 0x0070, 0x0080 },
	{ 0x1670, 0x18d0, 0x1bc, 0x1dc,		0x1618, 0x0110, 0x0078, 0x0068 },

	{ 0x14d0, 0x14f0, 0x1bc, 0x1dc,		0x1618, 0x0110, 0x0078, 0x0068 },
	{ 0x14f0, 0x1670, 0x18c, 0x1bc,		0x1508, 0x0208, 0x0078, 0x0060 },

	{ 0x14d0, 0x15b0, 0x18c, 0x1bc,		0x1618, 0x0110, 0x0078, 0x0068 },
	{ 0x15b0, 0x1670, 0x18c, 0x1bc,		0x1580, 0x0128, 0x0070, 0x0080 },
	{ 0x1670, 0x18d0, 0x18c, 0x1bc,		0x1618, 0x0110, 0x0078, 0x0068 },

	{ 0x14d0, 0x18d0, 0x15c, 0x18c,		0x1618, 0x0110, 0x0078, 0x0068 },

	{ 0x14e0, 0x1840, 0x098, 0x15c,		0x16b0, 0x00b0, 0x0088, 0x0060 },
	{ 0x1840, 0x18d0, 0x088, 0x15c,		0x1770, 0x0118, 0x00c0, 0x0060 },

	{ 0x1250, 0x15a0, 0x000, 0x108,		0x1500, 0x0000, 0x0080, 0x0048 },
	{ 0x15a0, 0x16f0, 0x000, 0x098,		0x1698, 0x0000, 0x0080, 0x0050 },
	{ 0x16f0, 0x18d0, 0x000, 0x088,		0x1770, 0x0000, 0x00b8, 0x0060 },

	{ 0x1250, 0x14e0, 0x000, 0x10c,		0x1500, 0x0000, 0x0080, 0x0048 },
	{ 0x14e0, 0x15a0, 0x000, 0x09c,		0x1500, 0x0000, 0x0080, 0x0048 },
	{ 0x15a0, 0x16f0, 0x000, 0x09c,		0x1698, 0x0000, 0x0080, 0x0050 },
	{ 0x16f0, 0x1830, 0x000, 0x09c,		0x1770, 0x0000, 0x00b8, 0x0060 },
	{ 0x1830, 0x18d0, 0x000, 0x09c,		0x1770, 0x0118, 0x00c0, 0x0060 },

	{ 0x14e0, 0x1830, 0x09c, 0x158,		0x16b0, 0x00b0, 0x0088, 0x0060 },
	{ 0x1830, 0x18d0, 0x09c, 0x158,		0x1770, 0x0118, 0x00c0, 0x0060 },

	//--------------------------
	{ 0x14e0, 0x1650, 0x29c, 0x2f0,		0x15a8, 0x0268, 0x0080, 0x0058 },
	{ 0x14e0, 0x1610, 0x2f0, 0x3fc,		0x1518, 0x0368, 0x0090, 0x0058 },
	{ 0x14e0, 0x1630, 0x3fc, 0x46c,		0x1500, 0x03e8, 0x0090, 0x0058 },
	{ 0x14e0, 0x1630, 0x46c, 0x51c,		0x1508, 0x04f8, 0x0080, 0x0060 },
	{ 0x14e0, 0x15f0, 0x51c, 0x59c,		0x1508, 0x04f8, 0x0080, 0x0060 },
	{ 0x14e0, 0x15f0, 0x59c, 0x5d8,		0x1508, 0x0580, 0x0040, 0x0080 },
	{ 0x14e0, 0x1570, 0x5d8, 0x700,		0x1508, 0x05e8, 0x0040, 0x0088 },
	{ 0x1480, 0x1640, 0x700, 0x808,		0x1508, 0x0708, 0x0080, 0x0090 },

	{ 0x0000, 0x18d0, 0x000, 0x900,		0x1288, 0x0808, 0x0099, 0x00ce },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level06[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0x01a0, 0x0904, 0x0a04,	0x00d0, 0x0908, 0x00b0, 0x0090 },
	{ 0x01a0, 0x04e0, 0x0904, 0x0a04,	0x03d0, 0x0908, 0x00b0, 0x0038 },
	{ 0x04e0, 0x0740, 0x0904, 0x0a04,	0x0660, 0x0908, 0x00b0, 0x0098 },
	{ 0x0740, 0x0950, 0x0904, 0x0a04,	0x07e8, 0x0908, 0x00b8, 0x00b8 },
	{ 0x0950, 0x0a80, 0x0904, 0x0a04,	0x08f8, 0x0908, 0x00b0, 0x0080 },
	{ 0x0a80, 0x0da0, 0x0904, 0x0a04,	0x0cd0, 0x0908, 0x00b8, 0x00b0 },
	{ 0x0da0, 0x0f40, 0x0904, 0x0a04,	0x0e08, 0x0908, 0x00b8, 0x0070 },
	{ 0x0f40, 0x10c0, 0x0904, 0x0a04,	0x0fe8, 0x0908, 0x00b8, 0x0098 },
	{ 0x10c0, 0x1370, 0x0904, 0x0a04,	0x1140, 0x0908, 0x00b8, 0x0068 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level07[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0x0570, 0x0804, 0x0904,	0x0000, 0x0808, 0x0028, 0x00b8 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping level08[] =
{
	/* X1     X2      Y1     Y2     =>  SX      SY      PX      PY */
	{ 0x0000, 0xf000, 0x0000, 0xf000,	0x06f8, 0x0808, 0x0028, 0x00b8 },
	{ 0xff, 0, 0, 0, 0, 0, 0, 0 }
};

static const struct cchip_mapping *const levelData[]=
{
	level00,
	level01,
	level02,
	level03,
	level04,
	level05,
	level06,
	level07,
	level08
};

static void WriteLevelData(void)
{
	for (INT32 i = 0; i < 13; i++)
	{
		UINT16 v = CLEV[current_round][i];

		cval[2 * i + 0] = v & 0xff;
		cval[2 * i + 1] = v >> 8;
	}
}

static void WriteRestartPos(INT32 level)
{
	/*
        Cval0/1 = scroll x position
        Cval4/5 = player x screen position
        Cval2/3 = scroll y position
        Cval6/7 = player y screen position

        These are combined to find the absolute player position
        on the map, which is then given to the C-Chip in order
        for the restart position to be returned.
    */

	INT32 x = cval[0] + 256 * cval[1] + cval[4] + 256 * cval[5];
	INT32 y = cval[2] + 256 * cval[3] + cval[6] + 256 * cval[7];

	const struct cchip_mapping* thisLevel=levelData[level];

	while (thisLevel->xmin!=0xff)
	{
		if (x >= thisLevel->xmin && x < thisLevel->xmax &&
		    y >= thisLevel->ymin && y < thisLevel->ymax)
		{
			cval[0] = thisLevel->sx & 0xff;
			cval[1] = thisLevel->sx >> 8;
			cval[2] = thisLevel->sy & 0xff;
			cval[3] = thisLevel->sy >> 8;
			cval[4] = thisLevel->px & 0xff;
			cval[5] = thisLevel->px >> 8;
			cval[6] = thisLevel->py & 0xff;
			cval[7] = thisLevel->py >> 8;

			// Restart position found ok
			restart_status=0;

			return;
		}

		thisLevel++;
	}

	// No restart position found for this position (cval0-7 confirmed unchanged in this case)
	restart_status=0xff;
}

void BonzeWriteCChipBank(INT32 data)
{
	current_bank = data & 7;
}

void BonzeWriteCChipRam(INT32 offset, INT32 data)
{
	offset = (offset & 0xfff) / 2;

	if (current_bank == 0)
	{
		if (offset == 0x08)
		{
			cc_port = data;
			coin_lockout = ~data >> 6; // data & 0xc0
		//	coin_counter = data & 0x30;
		}

		if (offset == 0x0e && data != 0x00)
		{
			WriteRestartPos(current_round);
		}

		if (offset == 0x0f && data != 0x00)
		{
			WriteLevelData();
		}

		if (offset == 0x10)
		{
			current_round = data;
		}

		if (offset >= 0x11 && offset <= 0x2a)
		{
			cval[offset - 0x11] = data;
		}
	}
}

UINT16 BonzeReadCChipRam(INT32 offset)
{
	offset = (offset & 0xfff) / 2;

	if (current_bank == 0)
	{
		switch (offset)
		{
			case 0x03: return TaitoInput[0];		/* STARTn + SERVICE1 */
			case 0x04: return TaitoInput[1] & coin_lockout; /* COINn */
			case 0x05: return TaitoInput[2];    		/* Player controls + TILT */
			case 0x06: return TaitoInput[3];    		/* Player controls (cocktail) */
			case 0x08: return cc_port;
		}

		if (offset == 0x0e)
		{
			return restart_status; /* 0xff signals error, 0 signals ok */
		}

		if (offset >= 0x11 && offset <= 0x2a)
		{
			return cval[offset - 0x11];
		}
	}

	return 0;
}

void BonzeCChipReset()
{
	current_round = 0;
	current_bank = 0;
	coin_lockout = 0;

	memset (cval, 0, 26);
	cc_port = 0;
	restart_status = 0;
}

void BonzeCChipScan(INT32 nAction)
{
	struct BurnArea ba;
	
	if (nAction & ACB_MEMORY_RAM) {
		memset(&ba, 0, sizeof(ba));
		ba.Data	  = cval;
		ba.nLen	  = 26;
		ba.szName = "C-Chip Ram";
		BurnAcb(&ba);
	}
	
	if (nAction & ACB_DRIVER_DATA) {
		SCAN_VAR(current_round);
		SCAN_VAR(current_bank);
		SCAN_VAR(coin_lockout);
		SCAN_VAR(cc_port);
		SCAN_VAR(restart_status);
	}
}

/*************************************************************************

  Volfied C-Chip Protection
  =========================

  The C-Chip (Taito TC0030CMD) is an unidentified mask programmed
  microcontroller of some sort with 64 pins.  It probably has
  about 2k of ROM and 8k of RAM.

  Cheat:
    volfied:0:100191:00:001:Complete level with 99.9% Now!
    volfied:0:100192:99:501:Complete level with 99.9% Now! (2/3)
    volfied:0:100193:09:501:Complete level with 99.9% Now! (3/3)

*************************************************************************/

UINT8       volfied_current_bank;
UINT8       volfied_current_flag;
UINT8       volfied_cc_port;
UINT8       volfied_current_cmd;
UINT8  *    volfied_cchip_ram;

static const UINT16 palette_data_01[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x104a, 0xce41, 0x8c39, 0x5252, 0xd662, 0x4a31, 0x0000,
	0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x104a, 0xce41, 0x8c39, 0x5252, 0xd662, 0x4a31, 0x0000,
	0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0000, 0x0000, 0x0000,
	0x0000, 0xd62a, 0x1002, 0xce01, 0x5a3b, 0xde7b, 0x4a31, 0x0000,
	0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0038, 0x0e38, 0x0000
};

static const UINT16 palette_data_02[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x4008, 0x0029, 0xc641, 0x4c52, 0x5473, 0xde7b, 0x1863,
	0x524a, 0xce39, 0x0821, 0x9c01, 0x1200, 0x8001, 0xc002, 0xce39,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
	0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
	0x0000, 0x4208, 0x0c39, 0xd061, 0x547a, 0x1472, 0xde7b, 0xde7b,
	0x187b, 0x947a, 0x0821, 0x9e79, 0x1040, 0x8079, 0xc07a, 0x0000
};

static const UINT16 palette_data_03[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x4208, 0x0821,
	0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x1860, 0x1e78,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
	0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
	0x0000, 0xc001, 0x4002, 0x8002, 0xc002, 0xc002, 0x0001, 0xc001,
	0x9201, 0xc002, 0xc003, 0x0003, 0x8002, 0x4001, 0xc002, 0x4003
};

static const UINT16 palette_data_04[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x1042, 0xce39, 0x8c31, 0x524a, 0xd65a, 0x4a29, 0x0000,
	0x1e00, 0x1000, 0x8c21, 0xce29, 0x0039, 0x0038, 0x0e38, 0x0038,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x1002, 0xce01, 0x8c01, 0x5202, 0xd602, 0x4a01, 0x0000,
	0x1e00, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};

static const UINT16 palette_data_05[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x1200, 0x1600, 0x1a00, 0x9e01, 0x8021, 0xc029, 0x0032,
	0x803a, 0x4208, 0x0821, 0x1042, 0xd65a, 0x9c73, 0xde03, 0x5c02,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x5202, 0xd602, 0x5a03, 0xde03, 0x8021, 0xc029, 0x0032,
	0x803a, 0x4208, 0x0821, 0x1042, 0xd65a, 0x9c73, 0xde03, 0x5c02
};

static const UINT16 palette_data_06[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x9e52, 0x9028, 0x9428, 0x9828, 0x9e28, 0x4208, 0xde7b,
	0xde03, 0x9c02, 0xc03a, 0x0063, 0x586b, 0x9252, 0x8a31, 0x5e31,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0263, 0x9e52, 0x8058, 0x0879, 0x8c79, 0x107a, 0x4208, 0xde7b,
	0xde01, 0x1e01, 0xc03a, 0x0063, 0x586b, 0x9252, 0x8a31, 0x527a
};

static const UINT16 palette_data_07[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x4208, 0x0821,
	0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x1860, 0x1e78,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
	0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
	0x0000, 0x8001, 0x0002, 0x8002, 0x0003, 0x8003, 0x4208, 0x0821,
	0x8c31, 0x1042, 0x9c73, 0x1e00, 0x5c02, 0x0c00, 0x1860, 0x1e78
};

static const UINT16 palette_data_08[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x1042, 0xce39, 0x8c31, 0x524a, 0xd65a, 0x4a29, 0x0000,
	0x1e00, 0x1000, 0x9e01, 0x5e02, 0x5e03, 0x0038, 0x0e38, 0x0000,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x5202, 0x1002, 0xce19, 0x9432, 0x1843, 0x8c11, 0x0000,
	0x1e00, 0x1000, 0x9e01, 0x5e02, 0x5e03, 0x0038, 0x0e38, 0x0000
};

static const UINT16 palette_data_09[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x1048, 0x1250, 0x1458, 0x1660, 0xd418, 0x9e02, 0xc203,
	0x4208, 0x4a29, 0x8c31, 0x1042, 0x1e78, 0x166b, 0x0c38, 0x1868,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x1600, 0x1a21, 0x5c29, 0xde39, 0xd418, 0x9e02, 0xc203,
	0x4208, 0x4a29, 0x8c31, 0x1042, 0x1e42, 0x186b, 0x9210, 0x9e31
};

static const UINT16 palette_data_0a[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0xde7b,
	0xc001, 0xc003, 0xde03, 0x1403, 0xcc01, 0x4a01, 0x0668, 0x4672,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x0000, 0x0038, 0x4a29, 0x5401, 0x9c02, 0x9218, 0xde7b,
	0x0003, 0xc003, 0x5e02, 0xde01, 0x5201, 0xd200, 0x0668, 0x4672
};

static const UINT16 palette_data_0b[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0050, 0x8001, 0xc001, 0x0002, 0xc002, 0xd043, 0x9c73, 0x524a,
	0xce39, 0x8c31, 0x4208, 0xde03, 0x9c02, 0x1e60, 0x1a00, 0x1000,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x8c01, 0xce01, 0x1002, 0xd62a, 0xde4b, 0x9c73, 0x5202,
	0xce01, 0x8c01, 0x4208, 0xde03, 0x9c02, 0x1e60, 0x1a00, 0x1000
};

static const UINT16 palette_data_0c[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0x9e52,
	0xc001, 0xc003, 0x1e00, 0x1400, 0x0c00, 0x4a01, 0x0668, 0x4672,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0xde7b,
	0xc001, 0xc003, 0xde03, 0x1403, 0xcc01, 0x4a01, 0x0668, 0x4672
};

static const UINT16 palette_data_0d[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863,
	0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863,
	0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42,
	0x0000, 0x4208, 0x5029, 0x9431, 0xd839, 0x5a4a, 0x9e52, 0x5862,
	0xde4b, 0x8e39, 0x0821, 0x1600, 0x1000, 0xd201, 0x1e00, 0x0a42
};

static const UINT16 palette_data_0e[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0e01, 0x5001, 0x9201, 0xd401, 0x1602, 0x1200, 0x1600,
	0x4208, 0x0821, 0x8c31, 0x1042, 0x5a6b, 0x8001, 0x0002, 0x9a02,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
	0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
	0x0000, 0x8a21, 0x0a32, 0x4c3a, 0x8e4a, 0x504b, 0xd203, 0xc003,
	0x4208, 0x0821, 0x8c31, 0x1042, 0x5a6b, 0x8001, 0x0002, 0x545b
};

static const UINT16 palette_data_0f[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x0000, 0x0821,
	0x9c31, 0x1042, 0x9c73, 0x1e02, 0x1a02, 0x0c00, 0x4002, 0xc001,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
	0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
	0x0000, 0xce00, 0x5201, 0xd601, 0x5a02, 0xde02, 0x0000, 0x0821,
	0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x9e01, 0x0e00
};

static const UINT16 palette_data_10[0x50] =
{
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0601, 0x8a09, 0x0e1a, 0x922a, 0x163b, 0xde7b, 0xd65a,
	0xce39, 0x0821, 0x0000, 0x0c00, 0x5208, 0x1a02, 0x9e03, 0xce39,
	0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
	0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
	0x0000, 0x1400, 0x8002, 0x0068, 0x0000, 0x5e01, 0x5e02, 0x1e03,
	0xde03, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39,
	0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863,
	0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42
};

static const UINT16 palette_data_11[0x50] =
{
	0x0000, 0x4a29, 0x8c31, 0xce39, 0x1042, 0x524a, 0x9452, 0xd65a,
	0x1863, 0x0000, 0xde39, 0xde7b, 0xc001, 0x8002, 0x1800, 0x1e00,
	0x0000, 0xde7b, 0x1e00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
	0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00,
	0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00,
	0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03,
	0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03,
	0xde03, 0x0e00, 0x9e4a, 0x0000, 0x1042, 0xde7b, 0x9452, 0x4a29,
	0xce39, 0x1c02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};

static const UINT16 *const palette_data_lookup[] =
{
	0,
	palette_data_01,
	palette_data_02,
	palette_data_03,
	palette_data_04,
	palette_data_05,
	palette_data_06,
	palette_data_07,
	palette_data_08,
	palette_data_09,
	palette_data_0a,
	palette_data_0b,
	palette_data_0c,
	palette_data_0d,
	palette_data_0e,
	palette_data_0f,
	palette_data_10,
	palette_data_11
};


static void volfied_timer_callback()
{
	// Palette commands - palette data written to bank 0: $10 - $af
	if (volfied_current_cmd >= 0x1 && volfied_current_cmd < 0x12)
	{
		const UINT16* palette_data = palette_data_lookup[volfied_current_cmd];
		INT32 i;
		for (i = 0; i < 0x50; i++)
		{
			volfied_cchip_ram[0x10 + i * 2 + 0] = palette_data[i] >> 8;
			volfied_cchip_ram[0x10 + i * 2 + 1] = palette_data[i] & 0xff;
		}
	}

	// Unknown command - result written to bank 0: $23
	if (volfied_current_cmd >= 0x81 && volfied_current_cmd < 0x92)
	{
		switch (volfied_current_cmd)
		{
		case 0x81: volfied_cchip_ram[0x23] = 0xf; break;
		case 0x82: volfied_cchip_ram[0x23] = 0x1; break;
		case 0x83: volfied_cchip_ram[0x23] = 0x6; break;
		case 0x84: volfied_cchip_ram[0x23] = 0xf; break;
		case 0x85: volfied_cchip_ram[0x23] = 0x9; break;
		case 0x86: volfied_cchip_ram[0x23] = 0x6; break;
		case 0x87: volfied_cchip_ram[0x23] = 0x6; break;
		case 0x88: volfied_cchip_ram[0x23] = 0xf; break;
		case 0x89: volfied_cchip_ram[0x23] = 0x8; break;
		case 0x8a: volfied_cchip_ram[0x23] = 0x1; break;
		case 0x8b: volfied_cchip_ram[0x23] = 0xa; break;
		case 0x8c: volfied_cchip_ram[0x23] = 0x1; break;
		case 0x8d: volfied_cchip_ram[0x23] = 0x1; break;
		case 0x8e: volfied_cchip_ram[0x23] = 0x8; break;
		case 0x8f: volfied_cchip_ram[0x23] = 0x6; break;
		case 0x90: volfied_cchip_ram[0x23] = 0xa; break;
		case 0x91: volfied_cchip_ram[0x23] = 0x0; break;
		}
	}

	volfied_current_cmd = 0;
}

/*************************************
 *
 * Writes to C-Chip - Important Bits
 *
 *************************************/

void VolfiedCChipBankWrite(UINT16 data)
{
	volfied_current_bank = data & 7;
}

void VolfiedCChipRamWrite(INT32 offset, UINT8 data)
{
	volfied_cchip_ram[(volfied_current_bank * 0x400) + offset] = data;

//  if (offset != 0x8)
//      logerror("%08x:  volfied c write %04x %04x\n", cpu_get_pc(space->cpu), offset, data);

	if (volfied_current_bank == 0)
	{
		if (offset == 0x008)
		{
			volfied_cc_port = data;

//			coin_lockout_w(space->machine, 1, data & 0x80);
//			coin_lockout_w(space->machine, 0, data & 0x40);
//			coin_counter_w(space->machine, 1, data & 0x20);
//			coin_counter_w(space->machine, 0, data & 0x10);
		}

		if (offset == 0x3fe)
		{
			/*******************
            (This table stored in ROM at $146a8)
            (Level number stored at $100198.b, from $100118.b, from $100098.b)
            (Level number at $b34 stored to $100098.b)

            round 01 => data $0A
            round 02 => data $01
            round 03 => data $03
            round 04 => data $08
            round 05 => data $05
            round 06 => data $04
            round 07 => data $0B
            round 08 => data $09
            round 09 => data $07
            round 10 => data $06
            round 11 => data $0E
            round 12 => data $0D
            round 13 => data $02
            round 14 => data $0C
            round 15 => data $0F
            round 16 => data $10
            final    => data $11

            ********************/

			volfied_current_cmd = data;
			
			// Palette request cmd - verified to take around 122242 68000 cycles to complete
			if (volfied_current_cmd >= 0x1 && volfied_current_cmd < 0x12)
			{
				//space->machine->scheduler().timer_set(downcast<cpu_device *>(space->cpu)->cycles_to_attotime(122242), FUNC(volfied_timer_callback));
//				nTaitoCyclesDone[0] += SekRun(122242);
				volfied_timer_callback();
			}
			// Unknown cmd - verified to take around 105500 68000 cycles to complete
			else if (volfied_current_cmd >= 0x81 && volfied_current_cmd < 0x92)
			{
				//space->machine->scheduler().timer_set(downcast<cpu_device *>(space->cpu)->cycles_to_attotime(105500), FUNC(volfied_timer_callback));
//				nTaitoCyclesDone[0] += SekRun(105500);
				volfied_timer_callback();
			}
			else
			{
//				logerror("unknown cchip cmd %02x\n", data);
				volfied_current_cmd = 0;
			}
		}

		// Some kind of timer command
		if (offset == 0x3ff)
		{
			volfied_current_flag = data;
		}
	}
}


/*************************************
 *
 * Reads from C-Chip
 *
 *************************************/

UINT8 VolfiedCChipCtrlRead()
{
	return 0x01;
}

UINT8 VolfiedCChipRamRead(INT32 offset)
{
	/* Check for input ports */
	if (volfied_current_bank == 0)
	{
		switch (offset)
		{
		case 0x03: return TaitoInput[0];//input_port_read(space->machine, "F00007");    /* STARTn + SERVICE1 */
		case 0x04: return TaitoInput[1];//input_port_read(space->machine, "F00009");    /* COINn */
		case 0x05: return TaitoInput[2];//input_port_read(space->machine, "F0000B");    /* Player controls + TILT */
		case 0x06: return TaitoInput[3];//input_port_read(space->machine, "F0000D");    /* Player controls (cocktail) */
		case 0x08: return volfied_cc_port;
		}
	}

//  if (cpu_get_pc(space->cpu)!=0x15ca8 && cpu_get_pc(space->cpu)!=0x15cd8 && cpu_get_pc(space->cpu)!=0x15cde)
//      logerror("%08x:  volfied c read %04x (bank %04x)\n", cpu_get_pc(space->cpu), offset, volfied_current_bank);

	/* Unknown */
	if (volfied_current_bank == 2 && offset == 0x005)
	{
		/* Not fully understood - Game writes:
            0001a0c2:  volfied c write 0005 00aa
            0001a0ca:  volfied c write 0006 0055
            0001a0d2:  volfied c write 0004 0065

            Then expects 0x7c to replace the 0xaa some time later.
        */
		return 0x7c;                /* makes worm in round 1 appear */
	}

	/* Unknown - some kind of timer */
	if (volfied_current_bank == 0 && offset == 0x3ff)
	{
		return 2 * volfied_current_flag;    /* fixes freeze after shield runs out */
	}

	/* Current command status */
	if (volfied_current_bank == 0 && offset == 0x3fe)
	{
		return volfied_current_cmd;
	}

	return volfied_cchip_ram[(volfied_current_bank * 0x400) + offset];
}


/*************************************
 *
 * C-Chip State Saving
 *
 *************************************/

void VolfiedCChipInit()
{
	volfied_cchip_ram = (UINT8*)BurnMalloc(0x400 * 8);
	
	TaitoIC_VolfiedCChipInUse = 1;

//	state->save_item(NAME(state->volfied_current_bank));
//	state->save_item(NAME(state->volfied_current_cmd));
//	state->save_item(NAME(state->volfied_current_flag));
//	state->save_item(NAME(state->volfied_cc_port));
//	state->save_pointer(NAME(state->volfied_cchip_ram), 0x400 * 8);
}

void VolfiedCChipReset()
{
	volfied_current_bank = 0;
	volfied_current_flag = 0;
	volfied_cc_port = 0;
	volfied_current_cmd = 0;
}

void VolfiedCChipExit()
{
	BurnFree(volfied_cchip_ram);
}

void VolfiedCChipScan(INT32 nAction)
{
	struct BurnArea ba;
	
	if (nAction & ACB_MEMORY_RAM) {
		memset(&ba, 0, sizeof(ba));
		ba.Data	  = volfied_cchip_ram;
		ba.nLen	  = 0x400 * 8;
		ba.szName = "CChip Ram";
		BurnAcb(&ba);
	}
	
	if (nAction & ACB_DRIVER_DATA) {
		SCAN_VAR(volfied_current_bank);
		SCAN_VAR(volfied_current_flag);
		SCAN_VAR(volfied_cc_port);
		SCAN_VAR(volfied_current_cmd);
	}
}
